From 30b649981e2c14d3ec961a72455c359081af6749 Mon Sep 17 00:00:00 2001 From: Saif Ali Shaik Date: Tue, 19 May 2026 17:11:44 +0530 Subject: [PATCH 01/28] Split API reference into per-product pages for AgentKit and SaaSKit - Add Redocly CLI workflow: split monolithic spec into multi-file structure, then selectively bundle per-product specs with --remove-unused-components - Create openapi/agentkit.yaml and openapi/saaskit.yaml as custom root files that into the shared split structure - Add pnpm split-api script chaining split + bundle for both products - Add Scalar API reference pages at /agentkit/apis/ and /saaskit/apis/ - AgentKit page includes quickstart with auth, connected accounts, and tool execution - Update secondary nav: AgentKit links to /agentkit/apis/, SaaSKit to /saaskit/apis/ - Update path fallbacks in secondary-nav-utils for new routes - Existing /apis/ route with full combined spec remains unchanged --- openapi/agentkit.yaml | 121 + .../code_samples/go/api_v1_connections/get.go | 9 + .../post.go | 21 + .../go/api_v1_organizations/get.go | 6 + .../go/api_v1_organizations/post.go | 7 + .../go/api_v1_organizations_{id}/delete.go | 4 + .../go/api_v1_organizations_{id}/get.go | 10 + .../go/api_v1_organizations_{id}/patch.go | 8 + .../put.go | 4 + .../patch.go | 26 + .../get.go | 3 + .../post.go | 13 + .../patch.go | 3 + .../delete.go | 6 + .../get.go | 3 + .../put.go | 6 + .../delete.go | 5 + .../get.go | 5 + .../patch.go | 5 + .../patch.go | 5 + .../get.go | 1 + .../get.go | 10 + .../get.go | 9 + .../get.go | 1 + .../patch.go | 1 + .../patch.go | 1 + .../get.go | 3 + .../post.go | 5 + .../delete.go | 1 + .../get.go | 1 + .../get.go | 4 + .../post.go | 15 + .../get.go | 5 + .../get.go | 5 + .../api_v1_passwordless_email_resend/post.go | 9 + .../go/api_v1_passwordless_email_send/post.go | 22 + .../api_v1_passwordless_email_verify/post.go | 29 + .../code_samples/go/api_v1_permissions/get.go | 3 + .../go/api_v1_permissions/post.go | 9 + .../delete.go | 2 + .../get.go | 3 + .../put.go | 6 + openapi/code_samples/go/api_v1_roles/get.go | 3 + openapi/code_samples/go/api_v1_roles/post.go | 13 + .../go/api_v1_roles:set_defaults/patch.go | 3 + .../go/api_v1_roles_{role_name}/delete.go | 6 + .../go/api_v1_roles_{role_name}/get.go | 3 + .../go/api_v1_roles_{role_name}/put.go | 6 + .../get.go | 3 + .../get.go | 3 + .../post.go | 1 + .../delete.go | 2 + .../get.go | 3 + .../go/api_v1_sessions_{session_id}/get.go | 3 + .../post.go | 3 + openapi/code_samples/go/api_v1_users/get.go | 1 + .../go/api_v1_users_{id}/delete.go | 4 + .../code_samples/go/api_v1_users_{id}/get.go | 5 + .../go/api_v1_users_{id}/patch.go | 10 + .../go/api_v1_users_{user_id}_sessions/get.go | 15 + .../post.go | 3 + .../go/api_v1_webauthn_credentials/get.go | 3 + .../delete.go | 3 + .../patch.go | 7 + .../java/api_v1_connections/get.java | 7 + .../post.java | 22 + .../java/api_v1_organizations/get.java | 1 + .../java/api_v1_organizations/post.java | 5 + .../api_v1_organizations_{id}/delete.java | 7 + .../java/api_v1_organizations_{id}/get.java | 7 + .../java/api_v1_organizations_{id}/patch.java | 5 + .../put.java | 3 + .../patch.java | 13 + .../get.java | 1 + .../post.java | 16 + .../patch.java | 6 + .../delete.java | 5 + .../get.java | 1 + .../put.java | 12 + .../delete.java | 1 + .../get.java | 1 + .../patch.java | 1 + .../patch.java | 1 + .../get.java | 1 + .../get.java | 9 + .../get.java | 9 + .../get.java | 1 + .../patch.java | 3 + .../patch.java | 3 + .../get.java | 1 + .../post.java | 9 + .../delete.java | 1 + .../get.java | 1 + .../get.java | 6 + .../post.java | 18 + .../get.java | 2 + .../get.java | 2 + .../post.java | 1 + .../api_v1_passwordless_email_send/post.java | 18 + .../post.java | 18 + .../java/api_v1_permissions/get.java | 1 + .../java/api_v1_permissions/post.java | 10 + .../delete.java | 1 + .../get.java | 1 + .../put.java | 11 + .../code_samples/java/api_v1_roles/get.java | 1 + .../code_samples/java/api_v1_roles/post.java | 13 + .../java/api_v1_roles:set_defaults/patch.java | 5 + .../java/api_v1_roles_{role_name}/delete.java | 5 + .../java/api_v1_roles_{role_name}/get.java | 1 + .../java/api_v1_roles_{role_name}/put.java | 11 + .../get.java | 1 + .../get.java | 1 + .../post.java | 7 + .../delete.java | 1 + .../get.java | 1 + .../api_v1_sessions_{session_id}/get.java | 1 + .../post.java | 1 + .../code_samples/java/api_v1_users/get.java | 3 + .../java/api_v1_users_{id}/delete.java | 1 + .../java/api_v1_users_{id}/get.java | 2 + .../java/api_v1_users_{id}/patch.java | 11 + .../api_v1_users_{user_id}_sessions/get.java | 11 + .../post.java | 1 + .../java/api_v1_webauthn_credentials/get.java | 1 + .../delete.java | 1 + .../patch.java | 2 + .../javascript/api_v1_connections/get.js | 5 + .../post.js | 13 + .../javascript/api_v1_organizations/get.js | 3 + .../javascript/api_v1_organizations/post.js | 5 + .../api_v1_organizations_{id}/delete.js | 1 + .../api_v1_organizations_{id}/get.js | 7 + .../api_v1_organizations_{id}/patch.js | 4 + .../put.js | 1 + .../patch.js | 14 + .../get.js | 1 + .../post.js | 7 + .../patch.js | 3 + .../delete.js | 5 + .../get.js | 1 + .../put.js | 4 + .../delete.js | 1 + .../get.js | 4 + .../patch.js | 1 + .../patch.js | 1 + .../get.js | 1 + .../get.js | 4 + .../get.js | 4 + .../get.js | 4 + .../patch.js | 4 + .../patch.js | 1 + .../get.js | 10 + .../post.js | 8 + .../delete.js | 3 + .../get.js | 8 + .../get.js | 5 + .../post.js | 12 + .../get.js | 1 + .../get.js | 1 + .../api_v1_passwordless_email_resend/post.js | 6 + .../api_v1_passwordless_email_send/post.js | 13 + .../api_v1_passwordless_email_verify/post.js | 14 + .../javascript/api_v1_permissions/get.js | 1 + .../javascript/api_v1_permissions/post.js | 4 + .../delete.js | 1 + .../get.js | 1 + .../put.js | 4 + .../javascript/api_v1_roles/get.js | 1 + .../javascript/api_v1_roles/post.js | 7 + .../api_v1_roles:set_defaults/patch.js | 3 + .../api_v1_roles_{role_name}/delete.js | 5 + .../api_v1_roles_{role_name}/get.js | 1 + .../api_v1_roles_{role_name}/put.js | 4 + .../get.js | 1 + .../get.js | 1 + .../post.js | 1 + .../delete.js | 1 + .../get.js | 1 + .../api_v1_sessions_{session_id}/get.js | 1 + .../post.js | 1 + .../javascript/api_v1_users/get.js | 2 + .../javascript/api_v1_users_{id}/delete.js | 1 + .../javascript/api_v1_users_{id}/get.js | 1 + .../javascript/api_v1_users_{id}/patch.js | 9 + .../api_v1_users_{user_id}_sessions/get.js | 13 + .../post.js | 1 + .../api_v1_webauthn_credentials/get.js | 1 + .../delete.js | 1 + .../patch.js | 4 + .../python/api_v1_connections/get.py | 7 + .../delete.py | 3 + .../post.py | 12 + .../python/api_v1_organizations/get.py | 6 + .../python/api_v1_organizations/post.py | 6 + .../api_v1_organizations_{id}/delete.py | 1 + .../python/api_v1_organizations_{id}/get.py | 9 + .../python/api_v1_organizations_{id}/patch.py | 4 + .../put.py | 3 + .../patch.py | 14 + .../get.py | 1 + .../post.py | 14 + .../patch.py | 8 + .../delete.py | 12 + .../get.py | 4 + .../put.py | 10 + .../get.py | 13 + .../post.py | 19 + .../delete.py | 9 + .../get.py | 9 + .../patch.py | 19 + .../post.py | 12 + .../delete.py | 11 + .../delete.py | 4 + .../get.py | 4 + .../patch.py | 4 + .../patch.py | 4 + .../get.py | 3 + .../get.py | 3 + .../get.py | 3 + .../get.py | 4 + .../patch.py | 3 + .../patch.py | 3 + .../get.py | 7 + .../post.py | 5 + .../delete.py | 6 + .../get.py | 2 + .../get.py | 1 + .../post.py | 24 + .../get.py | 5 + .../get.py | 5 + .../api_v1_passwordless_email_resend/post.py | 6 + .../api_v1_passwordless_email_send/post.py | 14 + .../api_v1_passwordless_email_verify/post.py | 13 + .../python/api_v1_permissions/get.py | 1 + .../python/api_v1_permissions/post.py | 8 + .../delete.py | 3 + .../get.py | 3 + .../put.py | 9 + .../code_samples/python/api_v1_roles/get.py | 1 + .../code_samples/python/api_v1_roles/post.py | 11 + .../python/api_v1_roles:set_defaults/patch.py | 7 + .../python/api_v1_roles_{role_name}/delete.py | 8 + .../python/api_v1_roles_{role_name}/get.py | 1 + .../python/api_v1_roles_{role_name}/put.py | 9 + .../get.py | 1 + .../get.py | 1 + .../post.py | 4 + .../delete.py | 4 + .../get.py | 1 + .../api_v1_sessions_{session_id}/get.py | 1 + .../post.py | 1 + .../code_samples/python/api_v1_users/get.py | 2 + .../python/api_v1_users_{id}/delete.py | 2 + .../python/api_v1_users_{id}/get.py | 2 + .../python/api_v1_users_{id}/patch.py | 18 + .../api_v1_users_{user_id}_sessions/get.py | 18 + .../post.py | 1 + .../python/api_v1_webauthn_credentials/get.py | 1 + .../delete.py | 1 + .../patch.py | 4 + openapi/components/schemas/HelpInfoLink.yaml | 11 + ...ceUpdateOrganizationSessionPolicyBody.yaml | 47 + ...rviceUpsertUserManagementSettingsBody.yaml | 5 + .../RolesServiceAddPermissionsToRoleBody.yaml | 7 + ...iceUpdateDefaultOrganizationRolesBody.yaml | 7 + openapi/components/schemas/ScalekitEvent.yaml | 101 + openapi/components/schemas/TestUser.yaml | 27 + .../schemas/UserServiceResendInviteBody.yaml | 1 + .../ValidationErrorInfoFieldViolation.yaml | 10 + .../WebAuthConfigurationAttestation.yaml | 13 + ...thConfigurationAuthenticatorSelection.yaml | 7 + .../WebAuthConfigurationAuthenticators.yaml | 50 + .../schemas/WebAuthConfigurationRp.yaml | 19 + .../schemas/WebAuthConfigurationTimeout.yaml | 18 + .../WebAuthnCredentialAuthenticator.yaml | 21 + .../WebAuthnCredentialAuthenticatorFlags.yaml | 14 + .../schemas/WebAuthnCredentialClientInfo.yaml | 22 + .../schemas/WebAuthnCredentialUserAgent.yaml | 38 + .../WebAuthnServiceUpdateCredentialBody.yaml | 7 + .../authpasswordlessPasswordlessType.yaml | 5 + .../schemas/clientsClientSecret.yaml | 80 + .../schemas/clientsClientSecretStatus.yaml | 10 + ...ientsCreateOrganizationClientResponse.yaml | 10 + ...reateOrganizationClientSecretResponse.yaml | 10 + .../schemas/clientsCustomClaim.yaml | 16 + .../clientsGetOrganizationClientResponse.yaml | 5 + ...lientsListOrganizationClientsResponse.yaml | 39 + .../components/schemas/clientsM2MClient.yaml | 132 + .../schemas/clientsOrganizationClient.yaml | 60 + ...ientsUpdateOrganizationClientResponse.yaml | 5 + .../schemas/commonsExternalIdentity.yaml | 59 + .../schemas/commonsIdentityProviderType.yaml | 18 + .../schemas/commonsMembershipStatus.yaml | 6 + .../commonsOrganizationMembership.yaml | 82 + .../components/schemas/commonsRegionCode.yaml | 4 + openapi/components/schemas/commonsRole.yaml | 21 + .../components/schemas/commonsTimeUnit.yaml | 5 + .../schemas/commonsUserProfile.yaml | 163 + ...onnected_accountsAuthorizationDetails.yaml | 12 + .../connected_accountsConnectedAccount.yaml | 86 + ...ected_accountsConnectedAccountForList.yaml | 54 + .../connected_accountsConnectorStatus.yaml | 15 + .../connected_accountsConnectorType.yaml | 22 + ...accountsCreateConnectedAccountRequest.yaml | 38 + ...ccountsCreateConnectedAccountResponse.yaml | 7 + ...accountsDeleteConnectedAccountRequest.yaml | 31 + ...ccountsDeleteConnectedAccountResponse.yaml | 1 + ...tConnectedAccountByIdentifierResponse.yaml | 8 + ...etMagicLinkForConnectedAccountRequest.yaml | 43 + ...tMagicLinkForConnectedAccountResponse.yaml | 13 + .../connected_accountsGoogleDWDAuth.yaml | 37 + ...accountsListConnectedAccountsResponse.yaml | 32 + .../schemas/connected_accountsOauthToken.yaml | 34 + ...countsSearchConnectedAccountsResponse.yaml | 26 + .../schemas/connected_accountsStaticAuth.yaml | 11 + ...accountsUpdateConnectedAccountRequest.yaml | 43 + ...ccountsUpdateConnectedAccountResponse.yaml | 7 + ...untsVerifyConnectedAccountUserRequest.yaml | 17 + ...ntsVerifyConnectedAccountUserResponse.yaml | 7 + .../schemas/connectionsCodeChallengeType.yaml | 4 + .../schemas/connectionsConfigurationType.yaml | 4 + .../schemas/connectionsConnection.yaml | 128 + .../connectionsConnectionProvider.yaml | 18 + .../schemas/connectionsConnectionStatus.yaml | 5 + .../schemas/connectionsConnectionType.yaml | 14 + .../connectionsGetConnectionResponse.yaml | 8 + .../schemas/connectionsGoogleDWDConfig.yaml | 15 + .../schemas/connectionsIDPCertificate.yaml | 27 + .../schemas/connectionsListConnection.yaml | 58 + .../connectionsListConnectionsResponse.yaml | 8 + .../schemas/connectionsNameIdFormat.yaml | 6 + .../connectionsOAuthConnectionConfig.yaml | 106 + .../connectionsOIDCConnectionConfig.yaml | 94 + .../schemas/connectionsOIDCScope.yaml | 7 + .../schemas/connectionsOptionalScopes.yaml | 18 + .../connectionsPasswordLessConfig.yaml | 40 + .../schemas/connectionsPasswordlessType.yaml | 5 + .../schemas/connectionsRequestBinding.yaml | 4 + ...nnectionsSAMLConnectionConfigResponse.yaml | 121 + .../connectionsSAMLSigningOptions.yaml | 8 + .../schemas/connectionsStaticAuthConfig.yaml | 4 + .../connectionsToggleConnectionResponse.yaml | 14 + .../schemas/connectionsTokenAuthType.yaml | 4 + .../connectionsWebAuthConfiguration.yaml | 24 + .../schemas/directoriesAttributeMapping.yaml | 6 + .../schemas/directoriesAttributeMappings.yaml | 7 + .../schemas/directoriesDirectory.yaml | 103 + .../schemas/directoriesDirectoryGroup.yaml | 27 + .../schemas/directoriesDirectoryProvider.yaml | 9 + .../schemas/directoriesDirectoryType.yaml | 5 + .../schemas/directoriesDirectoryUser.yaml | 47 + .../directoriesGetDirectoryResponse.yaml | 5 + .../directoriesListDirectoriesResponse.yaml | 8 + ...irectoriesListDirectoryGroupsResponse.yaml | 24 + ...directoriesListDirectoryUsersResponse.yaml | 24 + .../schemas/directoriesRoleAssignment.yaml | 9 + .../schemas/directoriesRoleAssignments.yaml | 7 + .../components/schemas/directoriesSecret.yaml | 37 + .../schemas/directoriesSecretStatus.yaml | 3 + .../components/schemas/directoriesStats.yaml | 26 + .../directoriesToggleDirectoryResponse.yaml | 19 + .../schemas/domainsCreateDomainResponse.yaml | 7 + openapi/components/schemas/domainsDomain.yaml | 67 + .../components/schemas/domainsDomainType.yaml | 7 + .../schemas/domainsGetDomainResponse.yaml | 7 + .../schemas/domainsListDomainResponse.yaml | 22 + .../schemas/domainsVerificationMethod.yaml | 5 + .../schemas/domainsVerificationStatus.yaml | 6 + .../schemas/errdetailsDebugInfo.yaml | 11 + .../schemas/errdetailsErrorInfo.yaml | 18 + .../schemas/errdetailsHelpInfo.yaml | 13 + .../errdetailsLocalizedMessageInfo.yaml | 6 + .../schemas/errdetailsRequestInfo.yaml | 17 + .../schemas/errdetailsResourceInfo.yaml | 20 + .../schemas/errdetailsToolErrorInfo.yaml | 8 + .../errdetailsValidationErrorInfo.yaml | 11 + ...ganizationsCreateOrganizationResponse.yaml | 5 + .../schemas/organizationsFeature.yaml | 10 + ...ganizationsGeneratePortalLinkResponse.yaml | 8 + .../organizationsGetOrganizationResponse.yaml | 5 + ...sGetOrganizationSessionPolicyResponse.yaml | 5 + .../components/schemas/organizationsLink.yaml | 20 + ...rganizationsListOrganizationsResponse.yaml | 28 + .../schemas/organizationsOrganization.yaml | 77 + ...ionsOrganizationSessionPolicySettings.yaml | 49 + .../organizationsOrganizationSettings.yaml | 25 + ...anizationsOrganizationSettingsFeature.yaml | 23 + ...onsOrganizationUserManagementSettings.yaml | 12 + .../organizationsSessionPolicyType.yaml | 4 + ...ganizationsUpdateOrganizationResponse.yaml | 5 + ...dateOrganizationSessionPolicyResponse.yaml | 5 + ...sUpsertUserManagementSettingsResponse.yaml | 5 + ...passwordlessResendPasswordlessRequest.yaml | 10 + .../passwordlessSendPasswordlessRequest.yaml | 65 + .../passwordlessSendPasswordlessResponse.yaml | 37 + .../schemas/passwordlessTemplateType.yaml | 4 + ...passwordlessVerifyPasswordLessRequest.yaml | 25 + ...asswordlessVerifyPasswordLessResponse.yaml | 33 + .../components/schemas/protobufNullValue.yaml | 6 + .../rolesAddPermissionsToRoleResponse.yaml | 8 + .../rolesCreateOrganizationRoleResponse.yaml | 4 + .../rolesCreatePermissionResponse.yaml | 4 + .../schemas/rolesCreateRoleResponse.yaml | 12 + .../rolesGetOrganizationRoleResponse.yaml | 4 + .../schemas/rolesGetPermissionResponse.yaml | 4 + .../schemas/rolesGetRoleResponse.yaml | 14 + .../rolesGetRoleUsersCountResponse.yaml | 8 + .../rolesListDependentRolesResponse.yaml | 8 + ...sListEffectiveRolePermissionsResponse.yaml | 10 + .../rolesListOrganizationRolesResponse.yaml | 8 + .../schemas/rolesListPermissionsResponse.yaml | 23 + .../rolesListRolePermissionsResponse.yaml | 8 + .../schemas/rolesListRolesResponse.yaml | 17 + .../components/schemas/rolesPermission.yaml | 20 + .../schemas/rolesPermissionType.yaml | 4 + .../schemas/rolesRolePermission.yaml | 20 + ...pdateDefaultOrganizationRolesResponse.yaml | 10 + .../schemas/rolesUpdateDefaultRole.yaml | 9 + .../rolesUpdateDefaultRolesRequest.yaml | 34 + .../rolesUpdateDefaultRolesResponse.yaml | 22 + .../rolesUpdateOrganizationRoleResponse.yaml | 4 + .../rolesUpdatePermissionResponse.yaml | 4 + .../schemas/rolesUpdateRoleResponse.yaml | 10 + .../schemas/sessionsAuthenticatedClients.yaml | 17 + .../schemas/sessionsDeviceDetails.yaml | 63 + ...sessionsRevokeAllUserSessionsResponse.yaml | 18 + .../sessionsRevokeSessionResponse.yaml | 7 + .../sessionsRevokedSessionDetails.yaml | 77 + .../schemas/sessionsSessionDetails.yaml | 122 + .../schemas/sessionsUserSessionDetails.yaml | 33 + .../schemas/sessionsUserSessionFilter.yaml | 31 + .../schemas/toolsExecuteToolRequest.yaml | 64 + .../schemas/toolsExecuteToolResponse.yaml | 14 + .../usersCreateMembershipResponse.yaml | 4 + .../components/schemas/usersCreateUser.yaml | 36 + .../usersCreateUserAndMembershipResponse.yaml | 4 + .../schemas/usersCreateUserProfile.yaml | 76 + .../schemas/usersGetUserResponse.yaml | 4 + openapi/components/schemas/usersInvite.yaml | 48 + .../usersListOrganizationUsersResponse.yaml | 32 + .../usersListUserPermissionsResponse.yaml | 8 + .../schemas/usersListUserRolesResponse.yaml | 8 + .../schemas/usersListUsersResponse.yaml | 30 + .../components/schemas/usersPermission.yaml | 18 + .../schemas/usersResendInviteResponse.yaml | 13 + .../usersSearchOrganizationUsersResponse.yaml | 30 + .../schemas/usersSearchUsersResponse.yaml | 30 + .../usersUpdateMembershipResponse.yaml | 4 + .../schemas/usersUpdateUserProfile.yaml | 138 + .../schemas/usersUpdateUserResponse.yaml | 4 + openapi/components/schemas/usersUser.yaml | 65 + ...nected_accountsCreateConnectedAccount.yaml | 27 + ...nected_accountsUpdateConnectedAccount.yaml | 25 + .../schemas/v1domainsCreateDomain.yaml | 22 + .../v1organizationsCreateOrganization.yaml | 41 + .../v1organizationsUpdateOrganization.yaml | 47 + .../v1rolesCreateOrganizationRole.yaml | 32 + .../schemas/v1rolesCreatePermission.yaml | 12 + .../components/schemas/v1rolesCreateRole.yaml | 44 + openapi/components/schemas/v1rolesRole.yaml | 74 + .../components/schemas/v1rolesUpdateRole.yaml | 38 + .../schemas/v1sessionsLocation.yaml | 38 + .../schemas/v1usersCreateMembership.yaml | 27 + .../schemas/v1usersUpdateMembership.yaml | 20 + .../components/schemas/v1usersUpdateUser.yaml | 24 + ...webauthnAllAcceptedCredentialsOptions.yaml | 17 + .../webauthnDeleteCredentialResponse.yaml | 10 + .../webauthnListCredentialsResponse.yaml | 11 + .../webauthnUnknownCredentialOptions.yaml | 12 + .../webauthnUpdateCredentialResponse.yaml | 5 + .../schemas/webauthnWebAuthnCredential.yaml | 55 + openapi/openapi.yaml | 409 + openapi/paths/api_v1_connected_accounts.yaml | 182 + .../api_v1_connected_accounts:delete.yaml | 38 + .../api_v1_connected_accounts:search.yaml | 60 + .../paths/api_v1_connected_accounts_auth.yaml | 66 + .../api_v1_connected_accounts_details.yaml | 63 + .../api_v1_connected_accounts_magic_link.yaml | 35 + ...api_v1_connected_accounts_user_verify.yaml | 48 + openapi/paths/api_v1_connections.yaml | 49 + openapi/paths/api_v1_execute_tool.yaml | 52 + ...s_{organization_id}_users_{id}_resend.yaml | 80 + ...izations_{organization_id}_users_{id}.yaml | 165 + openapi/paths/api_v1_organizations.yaml | 105 + ..._organizations:external_{external_id}.yaml | 52 + openapi/paths/api_v1_organizations_{id}.yaml | 133 + ...pi_v1_organizations_{id}_portal_links.yaml | 70 + .../api_v1_organizations_{id}_settings.yaml | 73 + .../api_v1_organizations_{org_id}_roles.yaml | 106 + ...nizations_{org_id}_roles:set_defaults.yaml | 56 + ...anizations_{org_id}_roles_{role_name}.yaml | 187 + ...ganizations_{organization_id}_clients.yaml | 93 + ...{organization_id}_clients_{client_id}.yaml | 118 + ...ation_id}_clients_{client_id}_secrets.yaml | 38 + ...ients_{client_id}_secrets_{secret_id}.yaml | 39 + ...ns_{organization_id}_connections_{id}.yaml | 104 + ...nization_id}_connections_{id}:disable.yaml | 51 + ...anization_id}_connections_{id}:enable.yaml | 51 + ...zations_{organization_id}_directories.yaml | 40 + ...id}_directories_{directory_id}_groups.yaml | 84 + ..._id}_directories_{directory_id}_users.yaml | 86 + ...ns_{organization_id}_directories_{id}.yaml | 49 + ...nization_id}_directories_{id}:disable.yaml | 54 + ...anization_id}_directories_{id}:enable.yaml | 53 + ...ganizations_{organization_id}_domains.yaml | 166 + ...ations_{organization_id}_domains_{id}.yaml | 111 + ...ions_{organization_id}_session-policy.yaml | 71 + ...anization_id}_settings_usermanagement.yaml | 28 + ...organizations_{organization_id}_users.yaml | 120 + ...ations_{organization_id}_users:search.yaml | 69 + ...ation_id}_users_{user_id}_permissions.yaml | 50 + ...rganization_id}_users_{user_id}_roles.yaml | 50 + .../api_v1_passwordless_email_resend.yaml | 40 + .../paths/api_v1_passwordless_email_send.yaml | 41 + .../api_v1_passwordless_email_verify.yaml | 40 + openapi/paths/api_v1_permissions.yaml | 111 + .../api_v1_permissions_{permission_name}.yaml | 148 + openapi/paths/api_v1_roles.yaml | 102 + openapi/paths/api_v1_roles:set_defaults.yaml | 43 + openapi/paths/api_v1_roles_default.yaml | 26 + openapi/paths/api_v1_roles_{role_name}.yaml | 166 + .../api_v1_roles_{role_name}_dependents.yaml | 49 + .../api_v1_roles_{role_name}_permissions.yaml | 107 + ..._v1_roles_{role_name}_permissions:all.yaml | 34 + ...e_name}_permissions_{permission_name}.yaml | 56 + .../api_v1_roles_{role_name}_users:count.yaml | 49 + .../paths/api_v1_sessions_{session_id}.yaml | 46 + .../api_v1_sessions_{session_id}_revoke.yaml | 46 + openapi/paths/api_v1_users.yaml | 51 + openapi/paths/api_v1_users:search.yaml | 55 + openapi/paths/api_v1_users_{id}.yaml | 161 + .../api_v1_users_{user_id}_sessions.yaml | 97 + ...pi_v1_users_{user_id}_sessions_revoke.yaml | 50 + .../paths/api_v1_webauthn_credentials.yaml | 39 + ..._webauthn_credentials_{credential_id}.yaml | 92 + openapi/saaskit.yaml | 374 + .../webhooks/connected_account.created.yaml | 25 + .../webhooks/connected_account.deleted.yaml | 28 + ...onnected_account.magic_link_generated.yaml | 25 + .../connected_account.oauth_succeeded.yaml | 26 + ...onnected_account.oauth_tokens_fetched.yaml | 26 + ...onnected_account.token_refresh_failed.yaml | 26 + ...ected_account.token_refresh_succeeded.yaml | 27 + .../webhooks/connected_account.updated.yaml | 26 + openapi/webhooks/organization.created.yaml | 34 + openapi/webhooks/organization.deleted.yaml | 35 + .../organization.directory.group_created.yaml | 27 + .../organization.directory.group_deleted.yaml | 27 + .../organization.directory.group_updated.yaml | 27 + .../organization.directory.user_created.yaml | 51 + .../organization.directory.user_deleted.yaml | 25 + .../organization.directory.user_updated.yaml | 46 + .../organization.directory_disabled.yaml | 27 + .../organization.directory_enabled.yaml | 27 + .../webhooks/organization.sso_created.yaml | 25 + .../webhooks/organization.sso_deleted.yaml | 25 + .../webhooks/organization.sso_disabled.yaml | 27 + .../webhooks/organization.sso_enabled.yaml | 27 + openapi/webhooks/organization.updated.yaml | 34 + openapi/webhooks/permission.created.yaml | 23 + openapi/webhooks/permission.deleted.yaml | 23 + openapi/webhooks/permission.updated.yaml | 23 + openapi/webhooks/role.created.yaml | 25 + openapi/webhooks/role.deleted.yaml | 25 + openapi/webhooks/role.updated.yaml | 25 + openapi/webhooks/user.login.yaml | 84 + openapi/webhooks/user.logout.yaml | 84 + .../user.organization_invitation.yaml | 66 + .../user.organization_membership_created.yaml | 66 + .../user.organization_membership_deleted.yaml | 66 + .../user.organization_membership_updated.yaml | 68 + openapi/webhooks/user.signup.yaml | 58 + package.json | 3 + pnpm-lock.yaml | 983 ++ public/api/agentkit.scalar.yaml | 1424 +++ public/api/saaskit.scalar.yaml | 9584 +++++++++++++++++ redocly.yaml | 8 + src/configs/secondary-nav.config.ts | 4 +- src/configs/sidebar.config.ts | 1 + src/pages/agentkit/apis.astro | 250 + src/pages/saaskit/apis.astro | 262 + src/utils/secondary-nav-utils.ts | 8 +- 583 files changed, 26300 insertions(+), 7 deletions(-) create mode 100644 openapi/agentkit.yaml create mode 100644 openapi/code_samples/go/api_v1_connections/get.go create mode 100644 openapi/code_samples/go/api_v1_memberships_organizations_{organization_id}_users_{id}/post.go create mode 100644 openapi/code_samples/go/api_v1_organizations/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations/post.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{id}/delete.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{id}/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{id}/patch.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{id}_portal_links/put.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{id}_settings/patch.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{org_id}_roles/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{org_id}_roles/post.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{org_id}_roles:set_defaults/patch.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/delete.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/put.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}/delete.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_directories/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_domains/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_domains/post.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_domains_{id}/delete.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_domains_{id}/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_users/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_users/post.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.go create mode 100644 openapi/code_samples/go/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.go create mode 100644 openapi/code_samples/go/api_v1_passwordless_email_resend/post.go create mode 100644 openapi/code_samples/go/api_v1_passwordless_email_send/post.go create mode 100644 openapi/code_samples/go/api_v1_passwordless_email_verify/post.go create mode 100644 openapi/code_samples/go/api_v1_permissions/get.go create mode 100644 openapi/code_samples/go/api_v1_permissions/post.go create mode 100644 openapi/code_samples/go/api_v1_permissions_{permission_name}/delete.go create mode 100644 openapi/code_samples/go/api_v1_permissions_{permission_name}/get.go create mode 100644 openapi/code_samples/go/api_v1_permissions_{permission_name}/put.go create mode 100644 openapi/code_samples/go/api_v1_roles/get.go create mode 100644 openapi/code_samples/go/api_v1_roles/post.go create mode 100644 openapi/code_samples/go/api_v1_roles:set_defaults/patch.go create mode 100644 openapi/code_samples/go/api_v1_roles_{role_name}/delete.go create mode 100644 openapi/code_samples/go/api_v1_roles_{role_name}/get.go create mode 100644 openapi/code_samples/go/api_v1_roles_{role_name}/put.go create mode 100644 openapi/code_samples/go/api_v1_roles_{role_name}_dependents/get.go create mode 100644 openapi/code_samples/go/api_v1_roles_{role_name}_permissions/get.go create mode 100644 openapi/code_samples/go/api_v1_roles_{role_name}_permissions/post.go create mode 100644 openapi/code_samples/go/api_v1_roles_{role_name}_permissions_{permission_name}/delete.go create mode 100644 openapi/code_samples/go/api_v1_roles_{role_name}_users:count/get.go create mode 100644 openapi/code_samples/go/api_v1_sessions_{session_id}/get.go create mode 100644 openapi/code_samples/go/api_v1_sessions_{session_id}_revoke/post.go create mode 100644 openapi/code_samples/go/api_v1_users/get.go create mode 100644 openapi/code_samples/go/api_v1_users_{id}/delete.go create mode 100644 openapi/code_samples/go/api_v1_users_{id}/get.go create mode 100644 openapi/code_samples/go/api_v1_users_{id}/patch.go create mode 100644 openapi/code_samples/go/api_v1_users_{user_id}_sessions/get.go create mode 100644 openapi/code_samples/go/api_v1_users_{user_id}_sessions_revoke/post.go create mode 100644 openapi/code_samples/go/api_v1_webauthn_credentials/get.go create mode 100644 openapi/code_samples/go/api_v1_webauthn_credentials_{credential_id}/delete.go create mode 100644 openapi/code_samples/go/api_v1_webauthn_credentials_{credential_id}/patch.go create mode 100644 openapi/code_samples/java/api_v1_connections/get.java create mode 100644 openapi/code_samples/java/api_v1_memberships_organizations_{organization_id}_users_{id}/post.java create mode 100644 openapi/code_samples/java/api_v1_organizations/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations/post.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{id}/delete.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{id}/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{id}/patch.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{id}_portal_links/put.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{id}_settings/patch.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{org_id}_roles/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{org_id}_roles/post.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{org_id}_roles:set_defaults/patch.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/delete.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/put.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}/delete.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_directories/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_domains/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_domains/post.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_domains_{id}/delete.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_domains_{id}/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_users/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_users/post.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.java create mode 100644 openapi/code_samples/java/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.java create mode 100644 openapi/code_samples/java/api_v1_passwordless_email_resend/post.java create mode 100644 openapi/code_samples/java/api_v1_passwordless_email_send/post.java create mode 100644 openapi/code_samples/java/api_v1_passwordless_email_verify/post.java create mode 100644 openapi/code_samples/java/api_v1_permissions/get.java create mode 100644 openapi/code_samples/java/api_v1_permissions/post.java create mode 100644 openapi/code_samples/java/api_v1_permissions_{permission_name}/delete.java create mode 100644 openapi/code_samples/java/api_v1_permissions_{permission_name}/get.java create mode 100644 openapi/code_samples/java/api_v1_permissions_{permission_name}/put.java create mode 100644 openapi/code_samples/java/api_v1_roles/get.java create mode 100644 openapi/code_samples/java/api_v1_roles/post.java create mode 100644 openapi/code_samples/java/api_v1_roles:set_defaults/patch.java create mode 100644 openapi/code_samples/java/api_v1_roles_{role_name}/delete.java create mode 100644 openapi/code_samples/java/api_v1_roles_{role_name}/get.java create mode 100644 openapi/code_samples/java/api_v1_roles_{role_name}/put.java create mode 100644 openapi/code_samples/java/api_v1_roles_{role_name}_dependents/get.java create mode 100644 openapi/code_samples/java/api_v1_roles_{role_name}_permissions/get.java create mode 100644 openapi/code_samples/java/api_v1_roles_{role_name}_permissions/post.java create mode 100644 openapi/code_samples/java/api_v1_roles_{role_name}_permissions_{permission_name}/delete.java create mode 100644 openapi/code_samples/java/api_v1_roles_{role_name}_users:count/get.java create mode 100644 openapi/code_samples/java/api_v1_sessions_{session_id}/get.java create mode 100644 openapi/code_samples/java/api_v1_sessions_{session_id}_revoke/post.java create mode 100644 openapi/code_samples/java/api_v1_users/get.java create mode 100644 openapi/code_samples/java/api_v1_users_{id}/delete.java create mode 100644 openapi/code_samples/java/api_v1_users_{id}/get.java create mode 100644 openapi/code_samples/java/api_v1_users_{id}/patch.java create mode 100644 openapi/code_samples/java/api_v1_users_{user_id}_sessions/get.java create mode 100644 openapi/code_samples/java/api_v1_users_{user_id}_sessions_revoke/post.java create mode 100644 openapi/code_samples/java/api_v1_webauthn_credentials/get.java create mode 100644 openapi/code_samples/java/api_v1_webauthn_credentials_{credential_id}/delete.java create mode 100644 openapi/code_samples/java/api_v1_webauthn_credentials_{credential_id}/patch.java create mode 100644 openapi/code_samples/javascript/api_v1_connections/get.js create mode 100644 openapi/code_samples/javascript/api_v1_memberships_organizations_{organization_id}_users_{id}/post.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations/post.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{id}/delete.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{id}/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{id}/patch.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{id}_portal_links/put.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{id}_settings/patch.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles/post.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles:set_defaults/patch.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/delete.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/put.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}/delete.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains/post.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains_{id}/delete.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains_{id}/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users/post.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.js create mode 100644 openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.js create mode 100644 openapi/code_samples/javascript/api_v1_passwordless_email_resend/post.js create mode 100644 openapi/code_samples/javascript/api_v1_passwordless_email_send/post.js create mode 100644 openapi/code_samples/javascript/api_v1_passwordless_email_verify/post.js create mode 100644 openapi/code_samples/javascript/api_v1_permissions/get.js create mode 100644 openapi/code_samples/javascript/api_v1_permissions/post.js create mode 100644 openapi/code_samples/javascript/api_v1_permissions_{permission_name}/delete.js create mode 100644 openapi/code_samples/javascript/api_v1_permissions_{permission_name}/get.js create mode 100644 openapi/code_samples/javascript/api_v1_permissions_{permission_name}/put.js create mode 100644 openapi/code_samples/javascript/api_v1_roles/get.js create mode 100644 openapi/code_samples/javascript/api_v1_roles/post.js create mode 100644 openapi/code_samples/javascript/api_v1_roles:set_defaults/patch.js create mode 100644 openapi/code_samples/javascript/api_v1_roles_{role_name}/delete.js create mode 100644 openapi/code_samples/javascript/api_v1_roles_{role_name}/get.js create mode 100644 openapi/code_samples/javascript/api_v1_roles_{role_name}/put.js create mode 100644 openapi/code_samples/javascript/api_v1_roles_{role_name}_dependents/get.js create mode 100644 openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions/get.js create mode 100644 openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions/post.js create mode 100644 openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions_{permission_name}/delete.js create mode 100644 openapi/code_samples/javascript/api_v1_roles_{role_name}_users:count/get.js create mode 100644 openapi/code_samples/javascript/api_v1_sessions_{session_id}/get.js create mode 100644 openapi/code_samples/javascript/api_v1_sessions_{session_id}_revoke/post.js create mode 100644 openapi/code_samples/javascript/api_v1_users/get.js create mode 100644 openapi/code_samples/javascript/api_v1_users_{id}/delete.js create mode 100644 openapi/code_samples/javascript/api_v1_users_{id}/get.js create mode 100644 openapi/code_samples/javascript/api_v1_users_{id}/patch.js create mode 100644 openapi/code_samples/javascript/api_v1_users_{user_id}_sessions/get.js create mode 100644 openapi/code_samples/javascript/api_v1_users_{user_id}_sessions_revoke/post.js create mode 100644 openapi/code_samples/javascript/api_v1_webauthn_credentials/get.js create mode 100644 openapi/code_samples/javascript/api_v1_webauthn_credentials_{credential_id}/delete.js create mode 100644 openapi/code_samples/javascript/api_v1_webauthn_credentials_{credential_id}/patch.js create mode 100644 openapi/code_samples/python/api_v1_connections/get.py create mode 100644 openapi/code_samples/python/api_v1_memberships_organizations_{organization_id}_users_{id}/delete.py create mode 100644 openapi/code_samples/python/api_v1_memberships_organizations_{organization_id}_users_{id}/post.py create mode 100644 openapi/code_samples/python/api_v1_organizations/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations/post.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{id}/delete.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{id}/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{id}/patch.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{id}_portal_links/put.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{id}_settings/patch.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{org_id}_roles/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{org_id}_roles/post.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{org_id}_roles:set_defaults/patch.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/delete.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/put.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_clients/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_clients/post.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/delete.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/patch.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}_secrets/post.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}_secrets_{secret_id}/delete.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}/delete.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_directories/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_domains/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_domains/post.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_domains_{id}/delete.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_domains_{id}/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_users/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_users/post.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.py create mode 100644 openapi/code_samples/python/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.py create mode 100644 openapi/code_samples/python/api_v1_passwordless_email_resend/post.py create mode 100644 openapi/code_samples/python/api_v1_passwordless_email_send/post.py create mode 100644 openapi/code_samples/python/api_v1_passwordless_email_verify/post.py create mode 100644 openapi/code_samples/python/api_v1_permissions/get.py create mode 100644 openapi/code_samples/python/api_v1_permissions/post.py create mode 100644 openapi/code_samples/python/api_v1_permissions_{permission_name}/delete.py create mode 100644 openapi/code_samples/python/api_v1_permissions_{permission_name}/get.py create mode 100644 openapi/code_samples/python/api_v1_permissions_{permission_name}/put.py create mode 100644 openapi/code_samples/python/api_v1_roles/get.py create mode 100644 openapi/code_samples/python/api_v1_roles/post.py create mode 100644 openapi/code_samples/python/api_v1_roles:set_defaults/patch.py create mode 100644 openapi/code_samples/python/api_v1_roles_{role_name}/delete.py create mode 100644 openapi/code_samples/python/api_v1_roles_{role_name}/get.py create mode 100644 openapi/code_samples/python/api_v1_roles_{role_name}/put.py create mode 100644 openapi/code_samples/python/api_v1_roles_{role_name}_dependents/get.py create mode 100644 openapi/code_samples/python/api_v1_roles_{role_name}_permissions/get.py create mode 100644 openapi/code_samples/python/api_v1_roles_{role_name}_permissions/post.py create mode 100644 openapi/code_samples/python/api_v1_roles_{role_name}_permissions_{permission_name}/delete.py create mode 100644 openapi/code_samples/python/api_v1_roles_{role_name}_users:count/get.py create mode 100644 openapi/code_samples/python/api_v1_sessions_{session_id}/get.py create mode 100644 openapi/code_samples/python/api_v1_sessions_{session_id}_revoke/post.py create mode 100644 openapi/code_samples/python/api_v1_users/get.py create mode 100644 openapi/code_samples/python/api_v1_users_{id}/delete.py create mode 100644 openapi/code_samples/python/api_v1_users_{id}/get.py create mode 100644 openapi/code_samples/python/api_v1_users_{id}/patch.py create mode 100644 openapi/code_samples/python/api_v1_users_{user_id}_sessions/get.py create mode 100644 openapi/code_samples/python/api_v1_users_{user_id}_sessions_revoke/post.py create mode 100644 openapi/code_samples/python/api_v1_webauthn_credentials/get.py create mode 100644 openapi/code_samples/python/api_v1_webauthn_credentials_{credential_id}/delete.py create mode 100644 openapi/code_samples/python/api_v1_webauthn_credentials_{credential_id}/patch.py create mode 100644 openapi/components/schemas/HelpInfoLink.yaml create mode 100644 openapi/components/schemas/OrganizationServiceUpdateOrganizationSessionPolicyBody.yaml create mode 100644 openapi/components/schemas/OrganizationServiceUpsertUserManagementSettingsBody.yaml create mode 100644 openapi/components/schemas/RolesServiceAddPermissionsToRoleBody.yaml create mode 100644 openapi/components/schemas/RolesServiceUpdateDefaultOrganizationRolesBody.yaml create mode 100644 openapi/components/schemas/ScalekitEvent.yaml create mode 100644 openapi/components/schemas/TestUser.yaml create mode 100644 openapi/components/schemas/UserServiceResendInviteBody.yaml create mode 100644 openapi/components/schemas/ValidationErrorInfoFieldViolation.yaml create mode 100644 openapi/components/schemas/WebAuthConfigurationAttestation.yaml create mode 100644 openapi/components/schemas/WebAuthConfigurationAuthenticatorSelection.yaml create mode 100644 openapi/components/schemas/WebAuthConfigurationAuthenticators.yaml create mode 100644 openapi/components/schemas/WebAuthConfigurationRp.yaml create mode 100644 openapi/components/schemas/WebAuthConfigurationTimeout.yaml create mode 100644 openapi/components/schemas/WebAuthnCredentialAuthenticator.yaml create mode 100644 openapi/components/schemas/WebAuthnCredentialAuthenticatorFlags.yaml create mode 100644 openapi/components/schemas/WebAuthnCredentialClientInfo.yaml create mode 100644 openapi/components/schemas/WebAuthnCredentialUserAgent.yaml create mode 100644 openapi/components/schemas/WebAuthnServiceUpdateCredentialBody.yaml create mode 100644 openapi/components/schemas/authpasswordlessPasswordlessType.yaml create mode 100644 openapi/components/schemas/clientsClientSecret.yaml create mode 100644 openapi/components/schemas/clientsClientSecretStatus.yaml create mode 100644 openapi/components/schemas/clientsCreateOrganizationClientResponse.yaml create mode 100644 openapi/components/schemas/clientsCreateOrganizationClientSecretResponse.yaml create mode 100644 openapi/components/schemas/clientsCustomClaim.yaml create mode 100644 openapi/components/schemas/clientsGetOrganizationClientResponse.yaml create mode 100644 openapi/components/schemas/clientsListOrganizationClientsResponse.yaml create mode 100644 openapi/components/schemas/clientsM2MClient.yaml create mode 100644 openapi/components/schemas/clientsOrganizationClient.yaml create mode 100644 openapi/components/schemas/clientsUpdateOrganizationClientResponse.yaml create mode 100644 openapi/components/schemas/commonsExternalIdentity.yaml create mode 100644 openapi/components/schemas/commonsIdentityProviderType.yaml create mode 100644 openapi/components/schemas/commonsMembershipStatus.yaml create mode 100644 openapi/components/schemas/commonsOrganizationMembership.yaml create mode 100644 openapi/components/schemas/commonsRegionCode.yaml create mode 100644 openapi/components/schemas/commonsRole.yaml create mode 100644 openapi/components/schemas/commonsTimeUnit.yaml create mode 100644 openapi/components/schemas/commonsUserProfile.yaml create mode 100644 openapi/components/schemas/connected_accountsAuthorizationDetails.yaml create mode 100644 openapi/components/schemas/connected_accountsConnectedAccount.yaml create mode 100644 openapi/components/schemas/connected_accountsConnectedAccountForList.yaml create mode 100644 openapi/components/schemas/connected_accountsConnectorStatus.yaml create mode 100644 openapi/components/schemas/connected_accountsConnectorType.yaml create mode 100644 openapi/components/schemas/connected_accountsCreateConnectedAccountRequest.yaml create mode 100644 openapi/components/schemas/connected_accountsCreateConnectedAccountResponse.yaml create mode 100644 openapi/components/schemas/connected_accountsDeleteConnectedAccountRequest.yaml create mode 100644 openapi/components/schemas/connected_accountsDeleteConnectedAccountResponse.yaml create mode 100644 openapi/components/schemas/connected_accountsGetConnectedAccountByIdentifierResponse.yaml create mode 100644 openapi/components/schemas/connected_accountsGetMagicLinkForConnectedAccountRequest.yaml create mode 100644 openapi/components/schemas/connected_accountsGetMagicLinkForConnectedAccountResponse.yaml create mode 100644 openapi/components/schemas/connected_accountsGoogleDWDAuth.yaml create mode 100644 openapi/components/schemas/connected_accountsListConnectedAccountsResponse.yaml create mode 100644 openapi/components/schemas/connected_accountsOauthToken.yaml create mode 100644 openapi/components/schemas/connected_accountsSearchConnectedAccountsResponse.yaml create mode 100644 openapi/components/schemas/connected_accountsStaticAuth.yaml create mode 100644 openapi/components/schemas/connected_accountsUpdateConnectedAccountRequest.yaml create mode 100644 openapi/components/schemas/connected_accountsUpdateConnectedAccountResponse.yaml create mode 100644 openapi/components/schemas/connected_accountsVerifyConnectedAccountUserRequest.yaml create mode 100644 openapi/components/schemas/connected_accountsVerifyConnectedAccountUserResponse.yaml create mode 100644 openapi/components/schemas/connectionsCodeChallengeType.yaml create mode 100644 openapi/components/schemas/connectionsConfigurationType.yaml create mode 100644 openapi/components/schemas/connectionsConnection.yaml create mode 100644 openapi/components/schemas/connectionsConnectionProvider.yaml create mode 100644 openapi/components/schemas/connectionsConnectionStatus.yaml create mode 100644 openapi/components/schemas/connectionsConnectionType.yaml create mode 100644 openapi/components/schemas/connectionsGetConnectionResponse.yaml create mode 100644 openapi/components/schemas/connectionsGoogleDWDConfig.yaml create mode 100644 openapi/components/schemas/connectionsIDPCertificate.yaml create mode 100644 openapi/components/schemas/connectionsListConnection.yaml create mode 100644 openapi/components/schemas/connectionsListConnectionsResponse.yaml create mode 100644 openapi/components/schemas/connectionsNameIdFormat.yaml create mode 100644 openapi/components/schemas/connectionsOAuthConnectionConfig.yaml create mode 100644 openapi/components/schemas/connectionsOIDCConnectionConfig.yaml create mode 100644 openapi/components/schemas/connectionsOIDCScope.yaml create mode 100644 openapi/components/schemas/connectionsOptionalScopes.yaml create mode 100644 openapi/components/schemas/connectionsPasswordLessConfig.yaml create mode 100644 openapi/components/schemas/connectionsPasswordlessType.yaml create mode 100644 openapi/components/schemas/connectionsRequestBinding.yaml create mode 100644 openapi/components/schemas/connectionsSAMLConnectionConfigResponse.yaml create mode 100644 openapi/components/schemas/connectionsSAMLSigningOptions.yaml create mode 100644 openapi/components/schemas/connectionsStaticAuthConfig.yaml create mode 100644 openapi/components/schemas/connectionsToggleConnectionResponse.yaml create mode 100644 openapi/components/schemas/connectionsTokenAuthType.yaml create mode 100644 openapi/components/schemas/connectionsWebAuthConfiguration.yaml create mode 100644 openapi/components/schemas/directoriesAttributeMapping.yaml create mode 100644 openapi/components/schemas/directoriesAttributeMappings.yaml create mode 100644 openapi/components/schemas/directoriesDirectory.yaml create mode 100644 openapi/components/schemas/directoriesDirectoryGroup.yaml create mode 100644 openapi/components/schemas/directoriesDirectoryProvider.yaml create mode 100644 openapi/components/schemas/directoriesDirectoryType.yaml create mode 100644 openapi/components/schemas/directoriesDirectoryUser.yaml create mode 100644 openapi/components/schemas/directoriesGetDirectoryResponse.yaml create mode 100644 openapi/components/schemas/directoriesListDirectoriesResponse.yaml create mode 100644 openapi/components/schemas/directoriesListDirectoryGroupsResponse.yaml create mode 100644 openapi/components/schemas/directoriesListDirectoryUsersResponse.yaml create mode 100644 openapi/components/schemas/directoriesRoleAssignment.yaml create mode 100644 openapi/components/schemas/directoriesRoleAssignments.yaml create mode 100644 openapi/components/schemas/directoriesSecret.yaml create mode 100644 openapi/components/schemas/directoriesSecretStatus.yaml create mode 100644 openapi/components/schemas/directoriesStats.yaml create mode 100644 openapi/components/schemas/directoriesToggleDirectoryResponse.yaml create mode 100644 openapi/components/schemas/domainsCreateDomainResponse.yaml create mode 100644 openapi/components/schemas/domainsDomain.yaml create mode 100644 openapi/components/schemas/domainsDomainType.yaml create mode 100644 openapi/components/schemas/domainsGetDomainResponse.yaml create mode 100644 openapi/components/schemas/domainsListDomainResponse.yaml create mode 100644 openapi/components/schemas/domainsVerificationMethod.yaml create mode 100644 openapi/components/schemas/domainsVerificationStatus.yaml create mode 100644 openapi/components/schemas/errdetailsDebugInfo.yaml create mode 100644 openapi/components/schemas/errdetailsErrorInfo.yaml create mode 100644 openapi/components/schemas/errdetailsHelpInfo.yaml create mode 100644 openapi/components/schemas/errdetailsLocalizedMessageInfo.yaml create mode 100644 openapi/components/schemas/errdetailsRequestInfo.yaml create mode 100644 openapi/components/schemas/errdetailsResourceInfo.yaml create mode 100644 openapi/components/schemas/errdetailsToolErrorInfo.yaml create mode 100644 openapi/components/schemas/errdetailsValidationErrorInfo.yaml create mode 100644 openapi/components/schemas/organizationsCreateOrganizationResponse.yaml create mode 100644 openapi/components/schemas/organizationsFeature.yaml create mode 100644 openapi/components/schemas/organizationsGeneratePortalLinkResponse.yaml create mode 100644 openapi/components/schemas/organizationsGetOrganizationResponse.yaml create mode 100644 openapi/components/schemas/organizationsGetOrganizationSessionPolicyResponse.yaml create mode 100644 openapi/components/schemas/organizationsLink.yaml create mode 100644 openapi/components/schemas/organizationsListOrganizationsResponse.yaml create mode 100644 openapi/components/schemas/organizationsOrganization.yaml create mode 100644 openapi/components/schemas/organizationsOrganizationSessionPolicySettings.yaml create mode 100644 openapi/components/schemas/organizationsOrganizationSettings.yaml create mode 100644 openapi/components/schemas/organizationsOrganizationSettingsFeature.yaml create mode 100644 openapi/components/schemas/organizationsOrganizationUserManagementSettings.yaml create mode 100644 openapi/components/schemas/organizationsSessionPolicyType.yaml create mode 100644 openapi/components/schemas/organizationsUpdateOrganizationResponse.yaml create mode 100644 openapi/components/schemas/organizationsUpdateOrganizationSessionPolicyResponse.yaml create mode 100644 openapi/components/schemas/organizationsUpsertUserManagementSettingsResponse.yaml create mode 100644 openapi/components/schemas/passwordlessResendPasswordlessRequest.yaml create mode 100644 openapi/components/schemas/passwordlessSendPasswordlessRequest.yaml create mode 100644 openapi/components/schemas/passwordlessSendPasswordlessResponse.yaml create mode 100644 openapi/components/schemas/passwordlessTemplateType.yaml create mode 100644 openapi/components/schemas/passwordlessVerifyPasswordLessRequest.yaml create mode 100644 openapi/components/schemas/passwordlessVerifyPasswordLessResponse.yaml create mode 100644 openapi/components/schemas/protobufNullValue.yaml create mode 100644 openapi/components/schemas/rolesAddPermissionsToRoleResponse.yaml create mode 100644 openapi/components/schemas/rolesCreateOrganizationRoleResponse.yaml create mode 100644 openapi/components/schemas/rolesCreatePermissionResponse.yaml create mode 100644 openapi/components/schemas/rolesCreateRoleResponse.yaml create mode 100644 openapi/components/schemas/rolesGetOrganizationRoleResponse.yaml create mode 100644 openapi/components/schemas/rolesGetPermissionResponse.yaml create mode 100644 openapi/components/schemas/rolesGetRoleResponse.yaml create mode 100644 openapi/components/schemas/rolesGetRoleUsersCountResponse.yaml create mode 100644 openapi/components/schemas/rolesListDependentRolesResponse.yaml create mode 100644 openapi/components/schemas/rolesListEffectiveRolePermissionsResponse.yaml create mode 100644 openapi/components/schemas/rolesListOrganizationRolesResponse.yaml create mode 100644 openapi/components/schemas/rolesListPermissionsResponse.yaml create mode 100644 openapi/components/schemas/rolesListRolePermissionsResponse.yaml create mode 100644 openapi/components/schemas/rolesListRolesResponse.yaml create mode 100644 openapi/components/schemas/rolesPermission.yaml create mode 100644 openapi/components/schemas/rolesPermissionType.yaml create mode 100644 openapi/components/schemas/rolesRolePermission.yaml create mode 100644 openapi/components/schemas/rolesUpdateDefaultOrganizationRolesResponse.yaml create mode 100644 openapi/components/schemas/rolesUpdateDefaultRole.yaml create mode 100644 openapi/components/schemas/rolesUpdateDefaultRolesRequest.yaml create mode 100644 openapi/components/schemas/rolesUpdateDefaultRolesResponse.yaml create mode 100644 openapi/components/schemas/rolesUpdateOrganizationRoleResponse.yaml create mode 100644 openapi/components/schemas/rolesUpdatePermissionResponse.yaml create mode 100644 openapi/components/schemas/rolesUpdateRoleResponse.yaml create mode 100644 openapi/components/schemas/sessionsAuthenticatedClients.yaml create mode 100644 openapi/components/schemas/sessionsDeviceDetails.yaml create mode 100644 openapi/components/schemas/sessionsRevokeAllUserSessionsResponse.yaml create mode 100644 openapi/components/schemas/sessionsRevokeSessionResponse.yaml create mode 100644 openapi/components/schemas/sessionsRevokedSessionDetails.yaml create mode 100644 openapi/components/schemas/sessionsSessionDetails.yaml create mode 100644 openapi/components/schemas/sessionsUserSessionDetails.yaml create mode 100644 openapi/components/schemas/sessionsUserSessionFilter.yaml create mode 100644 openapi/components/schemas/toolsExecuteToolRequest.yaml create mode 100644 openapi/components/schemas/toolsExecuteToolResponse.yaml create mode 100644 openapi/components/schemas/usersCreateMembershipResponse.yaml create mode 100644 openapi/components/schemas/usersCreateUser.yaml create mode 100644 openapi/components/schemas/usersCreateUserAndMembershipResponse.yaml create mode 100644 openapi/components/schemas/usersCreateUserProfile.yaml create mode 100644 openapi/components/schemas/usersGetUserResponse.yaml create mode 100644 openapi/components/schemas/usersInvite.yaml create mode 100644 openapi/components/schemas/usersListOrganizationUsersResponse.yaml create mode 100644 openapi/components/schemas/usersListUserPermissionsResponse.yaml create mode 100644 openapi/components/schemas/usersListUserRolesResponse.yaml create mode 100644 openapi/components/schemas/usersListUsersResponse.yaml create mode 100644 openapi/components/schemas/usersPermission.yaml create mode 100644 openapi/components/schemas/usersResendInviteResponse.yaml create mode 100644 openapi/components/schemas/usersSearchOrganizationUsersResponse.yaml create mode 100644 openapi/components/schemas/usersSearchUsersResponse.yaml create mode 100644 openapi/components/schemas/usersUpdateMembershipResponse.yaml create mode 100644 openapi/components/schemas/usersUpdateUserProfile.yaml create mode 100644 openapi/components/schemas/usersUpdateUserResponse.yaml create mode 100644 openapi/components/schemas/usersUser.yaml create mode 100644 openapi/components/schemas/v1connected_accountsCreateConnectedAccount.yaml create mode 100644 openapi/components/schemas/v1connected_accountsUpdateConnectedAccount.yaml create mode 100644 openapi/components/schemas/v1domainsCreateDomain.yaml create mode 100644 openapi/components/schemas/v1organizationsCreateOrganization.yaml create mode 100644 openapi/components/schemas/v1organizationsUpdateOrganization.yaml create mode 100644 openapi/components/schemas/v1rolesCreateOrganizationRole.yaml create mode 100644 openapi/components/schemas/v1rolesCreatePermission.yaml create mode 100644 openapi/components/schemas/v1rolesCreateRole.yaml create mode 100644 openapi/components/schemas/v1rolesRole.yaml create mode 100644 openapi/components/schemas/v1rolesUpdateRole.yaml create mode 100644 openapi/components/schemas/v1sessionsLocation.yaml create mode 100644 openapi/components/schemas/v1usersCreateMembership.yaml create mode 100644 openapi/components/schemas/v1usersUpdateMembership.yaml create mode 100644 openapi/components/schemas/v1usersUpdateUser.yaml create mode 100644 openapi/components/schemas/webauthnAllAcceptedCredentialsOptions.yaml create mode 100644 openapi/components/schemas/webauthnDeleteCredentialResponse.yaml create mode 100644 openapi/components/schemas/webauthnListCredentialsResponse.yaml create mode 100644 openapi/components/schemas/webauthnUnknownCredentialOptions.yaml create mode 100644 openapi/components/schemas/webauthnUpdateCredentialResponse.yaml create mode 100644 openapi/components/schemas/webauthnWebAuthnCredential.yaml create mode 100644 openapi/openapi.yaml create mode 100644 openapi/paths/api_v1_connected_accounts.yaml create mode 100644 openapi/paths/api_v1_connected_accounts:delete.yaml create mode 100644 openapi/paths/api_v1_connected_accounts:search.yaml create mode 100644 openapi/paths/api_v1_connected_accounts_auth.yaml create mode 100644 openapi/paths/api_v1_connected_accounts_details.yaml create mode 100644 openapi/paths/api_v1_connected_accounts_magic_link.yaml create mode 100644 openapi/paths/api_v1_connected_accounts_user_verify.yaml create mode 100644 openapi/paths/api_v1_connections.yaml create mode 100644 openapi/paths/api_v1_execute_tool.yaml create mode 100644 openapi/paths/api_v1_invites_organizations_{organization_id}_users_{id}_resend.yaml create mode 100644 openapi/paths/api_v1_memberships_organizations_{organization_id}_users_{id}.yaml create mode 100644 openapi/paths/api_v1_organizations.yaml create mode 100644 openapi/paths/api_v1_organizations:external_{external_id}.yaml create mode 100644 openapi/paths/api_v1_organizations_{id}.yaml create mode 100644 openapi/paths/api_v1_organizations_{id}_portal_links.yaml create mode 100644 openapi/paths/api_v1_organizations_{id}_settings.yaml create mode 100644 openapi/paths/api_v1_organizations_{org_id}_roles.yaml create mode 100644 openapi/paths/api_v1_organizations_{org_id}_roles:set_defaults.yaml create mode 100644 openapi/paths/api_v1_organizations_{org_id}_roles_{role_name}.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_clients.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets_{secret_id}.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_connections_{id}.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_connections_{id}:disable.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_connections_{id}:enable.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_directories.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_directories_{directory_id}_groups.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_directories_{directory_id}_users.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_directories_{id}.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_directories_{id}:disable.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_directories_{id}:enable.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_domains.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_domains_{id}.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_session-policy.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_settings_usermanagement.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_users.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_users:search.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_users_{user_id}_permissions.yaml create mode 100644 openapi/paths/api_v1_organizations_{organization_id}_users_{user_id}_roles.yaml create mode 100644 openapi/paths/api_v1_passwordless_email_resend.yaml create mode 100644 openapi/paths/api_v1_passwordless_email_send.yaml create mode 100644 openapi/paths/api_v1_passwordless_email_verify.yaml create mode 100644 openapi/paths/api_v1_permissions.yaml create mode 100644 openapi/paths/api_v1_permissions_{permission_name}.yaml create mode 100644 openapi/paths/api_v1_roles.yaml create mode 100644 openapi/paths/api_v1_roles:set_defaults.yaml create mode 100644 openapi/paths/api_v1_roles_default.yaml create mode 100644 openapi/paths/api_v1_roles_{role_name}.yaml create mode 100644 openapi/paths/api_v1_roles_{role_name}_dependents.yaml create mode 100644 openapi/paths/api_v1_roles_{role_name}_permissions.yaml create mode 100644 openapi/paths/api_v1_roles_{role_name}_permissions:all.yaml create mode 100644 openapi/paths/api_v1_roles_{role_name}_permissions_{permission_name}.yaml create mode 100644 openapi/paths/api_v1_roles_{role_name}_users:count.yaml create mode 100644 openapi/paths/api_v1_sessions_{session_id}.yaml create mode 100644 openapi/paths/api_v1_sessions_{session_id}_revoke.yaml create mode 100644 openapi/paths/api_v1_users.yaml create mode 100644 openapi/paths/api_v1_users:search.yaml create mode 100644 openapi/paths/api_v1_users_{id}.yaml create mode 100644 openapi/paths/api_v1_users_{user_id}_sessions.yaml create mode 100644 openapi/paths/api_v1_users_{user_id}_sessions_revoke.yaml create mode 100644 openapi/paths/api_v1_webauthn_credentials.yaml create mode 100644 openapi/paths/api_v1_webauthn_credentials_{credential_id}.yaml create mode 100644 openapi/saaskit.yaml create mode 100644 openapi/webhooks/connected_account.created.yaml create mode 100644 openapi/webhooks/connected_account.deleted.yaml create mode 100644 openapi/webhooks/connected_account.magic_link_generated.yaml create mode 100644 openapi/webhooks/connected_account.oauth_succeeded.yaml create mode 100644 openapi/webhooks/connected_account.oauth_tokens_fetched.yaml create mode 100644 openapi/webhooks/connected_account.token_refresh_failed.yaml create mode 100644 openapi/webhooks/connected_account.token_refresh_succeeded.yaml create mode 100644 openapi/webhooks/connected_account.updated.yaml create mode 100644 openapi/webhooks/organization.created.yaml create mode 100644 openapi/webhooks/organization.deleted.yaml create mode 100644 openapi/webhooks/organization.directory.group_created.yaml create mode 100644 openapi/webhooks/organization.directory.group_deleted.yaml create mode 100644 openapi/webhooks/organization.directory.group_updated.yaml create mode 100644 openapi/webhooks/organization.directory.user_created.yaml create mode 100644 openapi/webhooks/organization.directory.user_deleted.yaml create mode 100644 openapi/webhooks/organization.directory.user_updated.yaml create mode 100644 openapi/webhooks/organization.directory_disabled.yaml create mode 100644 openapi/webhooks/organization.directory_enabled.yaml create mode 100644 openapi/webhooks/organization.sso_created.yaml create mode 100644 openapi/webhooks/organization.sso_deleted.yaml create mode 100644 openapi/webhooks/organization.sso_disabled.yaml create mode 100644 openapi/webhooks/organization.sso_enabled.yaml create mode 100644 openapi/webhooks/organization.updated.yaml create mode 100644 openapi/webhooks/permission.created.yaml create mode 100644 openapi/webhooks/permission.deleted.yaml create mode 100644 openapi/webhooks/permission.updated.yaml create mode 100644 openapi/webhooks/role.created.yaml create mode 100644 openapi/webhooks/role.deleted.yaml create mode 100644 openapi/webhooks/role.updated.yaml create mode 100644 openapi/webhooks/user.login.yaml create mode 100644 openapi/webhooks/user.logout.yaml create mode 100644 openapi/webhooks/user.organization_invitation.yaml create mode 100644 openapi/webhooks/user.organization_membership_created.yaml create mode 100644 openapi/webhooks/user.organization_membership_deleted.yaml create mode 100644 openapi/webhooks/user.organization_membership_updated.yaml create mode 100644 openapi/webhooks/user.signup.yaml create mode 100644 public/api/agentkit.scalar.yaml create mode 100644 public/api/saaskit.scalar.yaml create mode 100644 redocly.yaml create mode 100644 src/pages/agentkit/apis.astro create mode 100644 src/pages/saaskit/apis.astro diff --git a/openapi/agentkit.yaml b/openapi/agentkit.yaml new file mode 100644 index 000000000..20a5144cc --- /dev/null +++ b/openapi/agentkit.yaml @@ -0,0 +1,121 @@ +info: + title: AgentKit APIs + description: | + # Overview + + The AgentKit API gives your AI agents authenticated access to third-party apps — sending emails, reading calendars, creating tickets, querying databases, and more. Your agent calls a tool; Scalekit handles the OAuth flow, token storage, and API call. + + **Base URLs:** + + ``` + https://{your-subdomain}.scalekit.dev (Development) + https://{your-subdomain}.scalekit.com (Production) + ``` + + ## Quickstart + + ### 1. Get an access token + + Use your API credentials from the [Scalekit Dashboard](https://app.scalekit.com) → **Developers → Settings → API Credentials**. + + ```sh + curl -X POST https:///oauth/token \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + -d 'client_id={client_id}' \ + -d 'client_secret={client_secret}' \ + -d 'grant_type=client_credentials' + ``` + + ### 2. List connected accounts + + ```sh + curl https:///api/v1/connected_accounts \ + -H 'Authorization: Bearer {access_token}' + ``` + + ### 3. Execute a tool on behalf of a user + + ```sh + curl -X POST https:///api/v1/execute_tool \ + -H 'Authorization: Bearer {access_token}' \ + -H 'Content-Type: application/json' \ + -d '{ + "connected_account_id": "{connected_account_id}", + "tool_name": "gmail_fetch_emails", + "tool_input": { "max_results": 5 } + }' + ``` + + ## SDKs + + ```sh + npm install @scalekit-sdk/node # Node.js + pip install scalekit-sdk-python # Python + ``` + + For the full product guide, see the [AgentKit documentation](https://docs.scalekit.com/agentkit/quickstart/). + contact: + name: Scalekit Inc + url: https://scalekit.com + email: support@scalekit.com + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0 + version: 1.0.0 +paths: + /api/v1/connected_accounts: + $ref: paths/api_v1_connected_accounts.yaml + /api/v1/connected_accounts/auth: + $ref: paths/api_v1_connected_accounts_auth.yaml + /api/v1/connected_accounts/details: + $ref: paths/api_v1_connected_accounts_details.yaml + /api/v1/connected_accounts/magic_link: + $ref: paths/api_v1_connected_accounts_magic_link.yaml + /api/v1/connected_accounts/user/verify: + $ref: paths/api_v1_connected_accounts_user_verify.yaml + /api/v1/connected_accounts:delete: + $ref: paths/api_v1_connected_accounts:delete.yaml + /api/v1/connected_accounts:search: + $ref: paths/api_v1_connected_accounts:search.yaml + /api/v1/execute_tool: + $ref: paths/api_v1_execute_tool.yaml +tags: + - description: >- + Manage connected accounts for third-party integrations and OAuth + connections. Connected accounts represent authenticated access to external + services like Google, Notion, Slack, and other applications. + name: Connected Accounts +externalDocs: + description: AgentKit Docs + url: https://docs.scalekit.com/agentkit/quickstart/ +openapi: 3.1.1 +servers: + - url: https://$SCALEKIT_ENVIRONMENT_URL +components: + securitySchemes: + oauth2: + type: oauth2 + flows: + clientCredentials: + tokenUrl: https://$SCALEKIT_ENVIRONMENT_URL/oauth/token + scopes: + '': No scope required for client credentials flow +security: + - oauth2: [] +webhooks: + connected_account.created: + $ref: webhooks/connected_account.created.yaml + connected_account.updated: + $ref: webhooks/connected_account.updated.yaml + connected_account.deleted: + $ref: webhooks/connected_account.deleted.yaml + connected_account.magic_link_generated: + $ref: webhooks/connected_account.magic_link_generated.yaml + connected_account.oauth_tokens_fetched: + $ref: webhooks/connected_account.oauth_tokens_fetched.yaml + connected_account.token_refresh_succeeded: + $ref: webhooks/connected_account.token_refresh_succeeded.yaml + connected_account.token_refresh_failed: + $ref: webhooks/connected_account.token_refresh_failed.yaml + connected_account.oauth_succeeded: + $ref: webhooks/connected_account.oauth_succeeded.yaml \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_connections/get.go b/openapi/code_samples/go/api_v1_connections/get.go new file mode 100644 index 000000000..22a647360 --- /dev/null +++ b/openapi/code_samples/go/api_v1_connections/get.go @@ -0,0 +1,9 @@ +// List connections by organization id +connections, err := scalekitClient.Connection().ListConnections( + ctx, + organizationId +) + +// List connections by domain +connections, err := scalekitClient.Connection().ListConnectionsByDomain(ctx, + domain) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_memberships_organizations_{organization_id}_users_{id}/post.go b/openapi/code_samples/go/api_v1_memberships_organizations_{organization_id}_users_{id}/post.go new file mode 100644 index 000000000..31db829df --- /dev/null +++ b/openapi/code_samples/go/api_v1_memberships_organizations_{organization_id}_users_{id}/post.go @@ -0,0 +1,21 @@ +func main() { + scalekitClient := scalekit.NewScalekitClient( + os.Getenv("SCALEKIT_ENV_URL"), + os.Getenv("SCALEKIT_CLIENT_ID"), + os.Getenv("SCALEKIT_CLIENT_SECRET"), + ) + membership := &usersv1.CreateMembership{ + Roles: []*usersv1.Role{{Name: "admin"}}, + Metadata: map[string]string{ + "department": "engineering", + "location": "nyc-office", + }, + } + resp, + err := scalekitClient.User().CreateMembership( + context.Background(), "org_123", + "usr_123", membership, false) + if err != nil { + panic(err) + } +} \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations/get.go b/openapi/code_samples/go/api_v1_organizations/get.go new file mode 100644 index 000000000..49b2b7b3f --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations/get.go @@ -0,0 +1,6 @@ +organizations, err := scalekitClient.Organization.ListOrganizations( + ctx, + &scalekit.ListOrganizationOptions{ + PageSize: 10, + } +) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations/post.go b/openapi/code_samples/go/api_v1_organizations/post.go new file mode 100644 index 000000000..cb7a278db --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations/post.go @@ -0,0 +1,7 @@ +organization, err := ScalekitClient.Organization.CreateOrganization( + ctx, + name, + scalekit.CreateOrganizationOptions{ + ExternalID: "externalId", + }, +) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{id}/delete.go b/openapi/code_samples/go/api_v1_organizations_{id}/delete.go new file mode 100644 index 000000000..e7ccf1f9d --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{id}/delete.go @@ -0,0 +1,4 @@ +err := scalekitClient.Organization.DeleteOrganization( + ctx, + organizationId +) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{id}/get.go b/openapi/code_samples/go/api_v1_organizations_{id}/get.go new file mode 100644 index 000000000..96625b3ef --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{id}/get.go @@ -0,0 +1,10 @@ +scalekitClient := scalekit.NewScalekitClient( + , + , + +) + +organization, err := scalekitClient.Organization.GetOrganization( + ctx, + organizationId +) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{id}/patch.go b/openapi/code_samples/go/api_v1_organizations_{id}/patch.go new file mode 100644 index 000000000..b1fcba6c4 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{id}/patch.go @@ -0,0 +1,8 @@ +organization, err := scalekitClient.Organization.UpdateOrganization( + ctx, + organizationId, + &scalekit.UpdateOrganization{ + DisplayName: "displayName", + ExternalId: "externalId", + }, +) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{id}_portal_links/put.go b/openapi/code_samples/go/api_v1_organizations_{id}_portal_links/put.go new file mode 100644 index 000000000..8eef92c0a --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{id}_portal_links/put.go @@ -0,0 +1,4 @@ +link, err := scalekitClient.Organization.GeneratePortalLink( + ctx, + organizationId +) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{id}_settings/patch.go b/openapi/code_samples/go/api_v1_organizations_{id}_settings/patch.go new file mode 100644 index 000000000..a9b890bd4 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{id}_settings/patch.go @@ -0,0 +1,26 @@ +settings := OrganizationSettings{ + + Features: []Feature{ + + { + + Name: "sso", + + Enabled: true, + + }, + + { + + Name: "dir_sync", + + Enabled: true, + + }, + + }, + + } + + +organization,err := scalekitClient.Organization().UpdateOrganizationSettings(ctx, organizationId, settings) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{org_id}_roles/get.go b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles/get.go new file mode 100644 index 000000000..820a2e302 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles/get.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Role().ListOrganizationRoles(ctx, "org_123") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{org_id}_roles/post.go b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles/post.go new file mode 100644 index 000000000..81df936a3 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles/post.go @@ -0,0 +1,13 @@ +resp, err := scalekitClient.Role().CreateOrganizationRole(ctx, "org_123", &rolesv1.CreateOrganizationRole{ + + Name: "org_admin", + + DisplayName: "Org Admin", + + Description: proto.String("Organization-scoped role"), // optional + + Extends: proto.String("base_role_name"), // optional + + Permissions: []string{"perm.read", "perm.write"}, // optional + +}) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{org_id}_roles:set_defaults/patch.go b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles:set_defaults/patch.go new file mode 100644 index 000000000..8faba5c73 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles:set_defaults/patch.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Role().UpdateDefaultOrganizationRoles(ctx, "org_123", "org_member") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/delete.go b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/delete.go new file mode 100644 index 000000000..9ab3732bb --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/delete.go @@ -0,0 +1,6 @@ +// Basic delete +err := scalekitClient.Role().DeleteOrganizationRole(ctx, "org_123", "org_role_admin") +if err != nil { /* handle err */ } + +// With reassignment +err = scalekitClient.Role().DeleteOrganizationRole(ctx, "org_123", "org_role_admin", "org_role_member") \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/get.go b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/get.go new file mode 100644 index 000000000..105c1070d --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/get.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Role().GetOrganizationRole(ctx, "org_123", "org_admin") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/put.go b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/put.go new file mode 100644 index 000000000..0c9bb2592 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/put.go @@ -0,0 +1,6 @@ +resp, err := scalekitClient.Role().UpdateOrganizationRole(ctx, "org_123", "org_admin", &rolesv1.UpdateRole{ + DisplayName: "Org Admin (Updated)", + Description: "Updated org role description", +}) +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}/delete.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}/delete.go new file mode 100644 index 000000000..a9c1346e9 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}/delete.go @@ -0,0 +1,5 @@ +err := scalekitClient.Connection.DeleteConnection( + ctx, + organizationId, + connectionId, +) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}/get.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}/get.go new file mode 100644 index 000000000..dc1551311 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}/get.go @@ -0,0 +1,5 @@ +connection, err := scalekitClient.Connection.GetConnection( + ctx, + organizationId, + connectionId, +) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.go new file mode 100644 index 000000000..374d31c2f --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.go @@ -0,0 +1,5 @@ +err := scalekitClient.Connection.DisableConnection( + ctx, + organizationId, + connectionId, +) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.go new file mode 100644 index 000000000..9ad85db00 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.go @@ -0,0 +1,5 @@ +err := scalekitClient.Connection.EnableConnection( + ctx, + organizationId, + connectionId, +) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories/get.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories/get.go new file mode 100644 index 000000000..516985813 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories/get.go @@ -0,0 +1 @@ +directories,err := scalekitClient.Directory().ListDirectories(ctx, organizationId) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.go new file mode 100644 index 000000000..0cd1b3693 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.go @@ -0,0 +1,10 @@ +options := &ListDirectoryGroupsOptions{ + + PageSize: 10, + + PageToken:"", + + } + + +directoryGroups, err := scalekitClient.Directory().ListDirectoryGroups(ctx, organizationId, directoryId, options) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.go new file mode 100644 index 000000000..9f2f1a111 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.go @@ -0,0 +1,9 @@ +options := &ListDirectoryUsersOptions{ + + PageSize: 10, + + PageToken: "", + + } + +directoryUsers,err := scalekitClient.Directory().ListDirectoryUsers(ctx, organizationId, directoryId, options) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}/get.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}/get.go new file mode 100644 index 000000000..ce14642b7 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}/get.go @@ -0,0 +1 @@ +directory, err := scalekitClient.Directory().GetDirectory(ctx, organizationId, directoryId) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.go new file mode 100644 index 000000000..5f22bf297 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.go @@ -0,0 +1 @@ +disable,err := scalekitClient.Directory().DisableDirectory(ctx, organizationId, directoryId) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.go new file mode 100644 index 000000000..d5aeae801 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.go @@ -0,0 +1 @@ +enable,err := scalekitClient.Directory().EnableDirectory(ctx, organizationId, directoryId) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains/get.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains/get.go new file mode 100644 index 000000000..973c552bc --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains/get.go @@ -0,0 +1,3 @@ +domains, err := scalekitClient.Domain().ListDomains(ctx, "org_id", &scalekit.ListDomainOptions{ +DomainType: "ORGANIZATION_DOMAIN", +}) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains/post.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains/post.go new file mode 100644 index 000000000..ab60651b8 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains/post.go @@ -0,0 +1,5 @@ +domain, err := scalekitClient.Domain().CreateDomain(ctx, "org_id", "example.com", &scalekit.CreateDomainOptions{ + + DomainType: "ORGANIZATION_DOMAIN", + + }) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains_{id}/delete.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains_{id}/delete.go new file mode 100644 index 000000000..0371086bf --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains_{id}/delete.go @@ -0,0 +1 @@ +err = scalekitClient.Domain().DeleteDomain(ctx, "dom_123", "org_123") \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains_{id}/get.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains_{id}/get.go new file mode 100644 index 000000000..982265fd7 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_domains_{id}/get.go @@ -0,0 +1 @@ +domain, err := scalekitClient.Domain().GetDomain(ctx, "dom_123", "org_123") \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_users/get.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_users/get.go new file mode 100644 index 000000000..21ca6da26 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_users/get.go @@ -0,0 +1,4 @@ +list, + err := scalekitClient.User().ListOrganizationUsers(ctx, "org_123", &scalekit.ListUsersOptions{PageSize: +50}) if err != nil { /* handle error */ } +fmt.Println(list.Users) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_users/post.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_users/post.go new file mode 100644 index 000000000..95802aa2b --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_users/post.go @@ -0,0 +1,15 @@ +newUser := &usersv1.CreateUser{ + Email: "user@example.com", + ExternalId: "ext_12345a67b89c", + Metadata: map[string]string{ + "department": "engineering", + "location": "nyc-office", + }, + UserProfile: &usersv1.CreateUserProfile{ + FirstName: "John", + LastName: "Doe", + }, +} +cuResp, + err := scalekitClient.User().CreateUserAndMembership(ctx, "org_123", +newUser, false) if err != nil { /* handle error */ } \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.go new file mode 100644 index 000000000..ea53c57d8 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.go @@ -0,0 +1,5 @@ +resp, err := scalekitClient.User().ListUserPermissions(ctx, "org_123", "usr_123") +if err != nil { + // handle error +} +permissions := resp.Permissions \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.go b/openapi/code_samples/go/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.go new file mode 100644 index 000000000..95a735cc0 --- /dev/null +++ b/openapi/code_samples/go/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.go @@ -0,0 +1,5 @@ +resp, err := scalekitClient.User().ListUserRoles(ctx, "org_123", "usr_123") +if err != nil { + // handle error +} +roles := resp.Roles \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_passwordless_email_resend/post.go b/openapi/code_samples/go/api_v1_passwordless_email_resend/post.go new file mode 100644 index 000000000..6dc61c628 --- /dev/null +++ b/openapi/code_samples/go/api_v1_passwordless_email_resend/post.go @@ -0,0 +1,9 @@ +resendResponse, err := scalekitClient.Passwordless().ResendPasswordlessEmail( + ctx, + authRequestId, +) + +if err != nil { + // Handle error + return +} \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_passwordless_email_send/post.go b/openapi/code_samples/go/api_v1_passwordless_email_send/post.go new file mode 100644 index 000000000..3e5800d7d --- /dev/null +++ b/openapi/code_samples/go/api_v1_passwordless_email_send/post.go @@ -0,0 +1,22 @@ +templateType := scalekit.TemplateTypeSignin +response, err := scalekitClient.Passwordless().SendPasswordlessEmail( + ctx, + "john.doe@example.com", + &scalekit.SendPasswordlessOptions{ + Template: &templateType, + ExpiresIn: 100, + MagiclinkAuthUri: "https://www.google.com", + TemplateVariables: map[string]string{ + "employeeID": "EMP523", + "teamName": "Alpha Team", + "supportEmail": "support@yourcompany.com", + }, + }, +) + +if err != nil { + // Handle error + return +} + +authRequestId := response.AuthRequestId \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_passwordless_email_verify/post.go b/openapi/code_samples/go/api_v1_passwordless_email_verify/post.go new file mode 100644 index 000000000..1276cb70f --- /dev/null +++ b/openapi/code_samples/go/api_v1_passwordless_email_verify/post.go @@ -0,0 +1,29 @@ +// Verify with OTP code +verifyResponse, err := scalekitClient.Passwordless().VerifyPasswordlessEmail( + ctx, + &scalekit.VerifyPasswordlessOptions{ + Code: "123456", // OTP code + AuthRequestId: authRequestId, + }, +) + +if err != nil { + // Handle error + return +} + +// Verify with magic link token +verifyResponse, err := scalekitClient.Passwordless().VerifyPasswordlessEmail( + ctx, + &scalekit.VerifyPasswordlessOptions{ + LinkToken: linkToken, // Magic link token + }, +) + +if err != nil { + // Handle error + return +} + +// User verified successfully +userEmail := verifyResponse.Email \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_permissions/get.go b/openapi/code_samples/go/api_v1_permissions/get.go new file mode 100644 index 000000000..e131a75c3 --- /dev/null +++ b/openapi/code_samples/go/api_v1_permissions/get.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Permission().ListPermissions(ctx) +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_permissions/post.go b/openapi/code_samples/go/api_v1_permissions/post.go new file mode 100644 index 000000000..3cbb9035e --- /dev/null +++ b/openapi/code_samples/go/api_v1_permissions/post.go @@ -0,0 +1,9 @@ +resp, err := scalekitClient.Permission().CreatePermission(ctx, &rolesv1.CreatePermission{ + + Name: "read:users", + + Description: "Allows reading users", + +}) +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_permissions_{permission_name}/delete.go b/openapi/code_samples/go/api_v1_permissions_{permission_name}/delete.go new file mode 100644 index 000000000..1f7a17e29 --- /dev/null +++ b/openapi/code_samples/go/api_v1_permissions_{permission_name}/delete.go @@ -0,0 +1,2 @@ +err := scalekitClient.Permission().DeletePermission(ctx, "read:users") +if err != nil { /* handle err */ } \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_permissions_{permission_name}/get.go b/openapi/code_samples/go/api_v1_permissions_{permission_name}/get.go new file mode 100644 index 000000000..2f6fecca1 --- /dev/null +++ b/openapi/code_samples/go/api_v1_permissions_{permission_name}/get.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Permission().GetPermission(ctx, "read:users") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_permissions_{permission_name}/put.go b/openapi/code_samples/go/api_v1_permissions_{permission_name}/put.go new file mode 100644 index 000000000..0649bf21e --- /dev/null +++ b/openapi/code_samples/go/api_v1_permissions_{permission_name}/put.go @@ -0,0 +1,6 @@ +resp, err := scalekitClient.Permission().UpdatePermission(ctx, "read:users", &rolesv1.CreatePermission{ + Name: "read:users", + Description: "Allows reading user resources", +}) +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_roles/get.go b/openapi/code_samples/go/api_v1_roles/get.go new file mode 100644 index 000000000..a137ea638 --- /dev/null +++ b/openapi/code_samples/go/api_v1_roles/get.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Role().ListRoles(ctx) +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_roles/post.go b/openapi/code_samples/go/api_v1_roles/post.go new file mode 100644 index 000000000..d88e009bd --- /dev/null +++ b/openapi/code_samples/go/api_v1_roles/post.go @@ -0,0 +1,13 @@ +resp, err := scalekitClient.Role().CreateRole(ctx, &rolesv1.CreateRole{ + + Name: "admin", + + DisplayName: "Admin", + + Description: "Environment-level role", + + Extends: proto.String("base_role"), // optional + + Permissions: []string{"read:users"}, // optional + +}) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_roles:set_defaults/patch.go b/openapi/code_samples/go/api_v1_roles:set_defaults/patch.go new file mode 100644 index 000000000..50f057634 --- /dev/null +++ b/openapi/code_samples/go/api_v1_roles:set_defaults/patch.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Role().UpdateDefaultRoles(ctx, "member") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_roles_{role_name}/delete.go b/openapi/code_samples/go/api_v1_roles_{role_name}/delete.go new file mode 100644 index 000000000..0429cbb6a --- /dev/null +++ b/openapi/code_samples/go/api_v1_roles_{role_name}/delete.go @@ -0,0 +1,6 @@ +// Basic delete +err := scalekitClient.Role().DeleteRole(ctx, "admin") +if err != nil { /* handle err */ } + +// With reassignment +err = scalekitClient.Role().DeleteRole(ctx, "admin", "member") \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_roles_{role_name}/get.go b/openapi/code_samples/go/api_v1_roles_{role_name}/get.go new file mode 100644 index 000000000..38c9c8ea5 --- /dev/null +++ b/openapi/code_samples/go/api_v1_roles_{role_name}/get.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Role().GetRole(ctx, "admin") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_roles_{role_name}/put.go b/openapi/code_samples/go/api_v1_roles_{role_name}/put.go new file mode 100644 index 000000000..cbf06e489 --- /dev/null +++ b/openapi/code_samples/go/api_v1_roles_{role_name}/put.go @@ -0,0 +1,6 @@ +resp, err := scalekitClient.Role().UpdateRole(ctx, "admin", &rolesv1.UpdateRole{ + DisplayName: "Admin (Updated)", + Description: "Updated description", +}) +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_roles_{role_name}_dependents/get.go b/openapi/code_samples/go/api_v1_roles_{role_name}_dependents/get.go new file mode 100644 index 000000000..17825dc14 --- /dev/null +++ b/openapi/code_samples/go/api_v1_roles_{role_name}_dependents/get.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Role().ListDependentRoles(ctx, "admin") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_roles_{role_name}_permissions/get.go b/openapi/code_samples/go/api_v1_roles_{role_name}_permissions/get.go new file mode 100644 index 000000000..0c10380f0 --- /dev/null +++ b/openapi/code_samples/go/api_v1_roles_{role_name}_permissions/get.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Permission().ListRolePermissions(ctx, "admin") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_roles_{role_name}_permissions/post.go b/openapi/code_samples/go/api_v1_roles_{role_name}_permissions/post.go new file mode 100644 index 000000000..3f7c800ec --- /dev/null +++ b/openapi/code_samples/go/api_v1_roles_{role_name}_permissions/post.go @@ -0,0 +1 @@ +resp, err := scalekitClient.Permission().AddPermissionsToRole(ctx, "role_admin", []string{"perm.read", "perm.write"}) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_roles_{role_name}_permissions_{permission_name}/delete.go b/openapi/code_samples/go/api_v1_roles_{role_name}_permissions_{permission_name}/delete.go new file mode 100644 index 000000000..4a42a624e --- /dev/null +++ b/openapi/code_samples/go/api_v1_roles_{role_name}_permissions_{permission_name}/delete.go @@ -0,0 +1,2 @@ +err := scalekitClient.Permission().RemovePermissionFromRole(ctx, "admin", "read:users") +if err != nil { /* handle err */ } \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_roles_{role_name}_users:count/get.go b/openapi/code_samples/go/api_v1_roles_{role_name}_users:count/get.go new file mode 100644 index 000000000..bfda52dec --- /dev/null +++ b/openapi/code_samples/go/api_v1_roles_{role_name}_users:count/get.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Role().GetRoleUsersCount(ctx, "admin") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_sessions_{session_id}/get.go b/openapi/code_samples/go/api_v1_sessions_{session_id}/get.go new file mode 100644 index 000000000..626f36c91 --- /dev/null +++ b/openapi/code_samples/go/api_v1_sessions_{session_id}/get.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Session().GetSession(ctx, "ses_123456789") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_sessions_{session_id}_revoke/post.go b/openapi/code_samples/go/api_v1_sessions_{session_id}_revoke/post.go new file mode 100644 index 000000000..0a0b2d7bd --- /dev/null +++ b/openapi/code_samples/go/api_v1_sessions_{session_id}_revoke/post.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Session().RevokeSession(ctx, "ses_123456789") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_users/get.go b/openapi/code_samples/go/api_v1_users/get.go new file mode 100644 index 000000000..2657fcca4 --- /dev/null +++ b/openapi/code_samples/go/api_v1_users/get.go @@ -0,0 +1 @@ +all, err := scalekitClient.User().ListUsers(ctx, &scalekit.ListUsersOptions{PageSize: 100}) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_users_{id}/delete.go b/openapi/code_samples/go/api_v1_users_{id}/delete.go new file mode 100644 index 000000000..2c8bc47c4 --- /dev/null +++ b/openapi/code_samples/go/api_v1_users_{id}/delete.go @@ -0,0 +1,4 @@ +if err := scalekitClient.User().DeleteUser(ctx, + "usr_123"); err != nil { + panic(err) +} \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_users_{id}/get.go b/openapi/code_samples/go/api_v1_users_{id}/get.go new file mode 100644 index 000000000..c8f329787 --- /dev/null +++ b/openapi/code_samples/go/api_v1_users_{id}/get.go @@ -0,0 +1,5 @@ +resp, err := scalekitClient.User().GetUser(ctx, "usr_123456") +if err != nil { + // handle error +} +user := resp.User \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_users_{id}/patch.go b/openapi/code_samples/go/api_v1_users_{id}/patch.go new file mode 100644 index 000000000..ce50c7d9e --- /dev/null +++ b/openapi/code_samples/go/api_v1_users_{id}/patch.go @@ -0,0 +1,10 @@ +upd := &usersv1.UpdateUser{ + UserProfile: &usersv1.UpdateUserProfile{ + FirstName: "John", + LastName: "Smith", + }, + Metadata: map[string]string{ + "department": "sales", + }, +} +scalekitClient.User().UpdateUser(ctx, "usr_123", upd) \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_users_{user_id}_sessions/get.go b/openapi/code_samples/go/api_v1_users_{user_id}_sessions/get.go new file mode 100644 index 000000000..1a4ce7df2 --- /dev/null +++ b/openapi/code_samples/go/api_v1_users_{user_id}_sessions/get.go @@ -0,0 +1,15 @@ +// Basic usage +resp, err := scalekitClient.Session().GetUserSessions(ctx, "user_123", 0, "", nil) +if err != nil { /* handle err */ } + +// With pagination and filtering +// import "time", sessionsv1 "...", "google.golang.org/protobuf/types/known/timestamppb" +startTime, _ := time.Parse(time.RFC3339, "2024-01-01T00:00:00Z") +endTime, _ := time.Parse(time.RFC3339, "2024-12-31T23:59:59Z") +filter := &sessionsv1.UserSessionFilter{ + Status: []string{"ACTIVE"}, + StartTime: timestamppb.New(startTime), + EndTime: timestamppb.New(endTime), +} +resp, err := scalekitClient.Session().GetUserSessions(ctx, "user_123", 10, "next_page_token", filter) +if err != nil { /* handle err */ } \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_users_{user_id}_sessions_revoke/post.go b/openapi/code_samples/go/api_v1_users_{user_id}_sessions_revoke/post.go new file mode 100644 index 000000000..9c1f5e2d2 --- /dev/null +++ b/openapi/code_samples/go/api_v1_users_{user_id}_sessions_revoke/post.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.Session().RevokeAllUserSessions(ctx, "user_123") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_webauthn_credentials/get.go b/openapi/code_samples/go/api_v1_webauthn_credentials/get.go new file mode 100644 index 000000000..3f2ef0c06 --- /dev/null +++ b/openapi/code_samples/go/api_v1_webauthn_credentials/get.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.WebAuthn().ListCredentials(ctx, "user_123") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_webauthn_credentials_{credential_id}/delete.go b/openapi/code_samples/go/api_v1_webauthn_credentials_{credential_id}/delete.go new file mode 100644 index 000000000..1aa33aece --- /dev/null +++ b/openapi/code_samples/go/api_v1_webauthn_credentials_{credential_id}/delete.go @@ -0,0 +1,3 @@ +resp, err := scalekitClient.WebAuthn().DeleteCredential(ctx, "wac_123") +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/go/api_v1_webauthn_credentials_{credential_id}/patch.go b/openapi/code_samples/go/api_v1_webauthn_credentials_{credential_id}/patch.go new file mode 100644 index 000000000..ed57438a5 --- /dev/null +++ b/openapi/code_samples/go/api_v1_webauthn_credentials_{credential_id}/patch.go @@ -0,0 +1,7 @@ +resp, err := scalekitClient.WebAuthn().UpdateCredential( + ctx, + "wac_123", + "Work Laptop Passkey", +) +if err != nil { /* handle err */ } +_ = resp \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_connections/get.java b/openapi/code_samples/java/api_v1_connections/get.java new file mode 100644 index 000000000..90e89f935 --- /dev/null +++ b/openapi/code_samples/java/api_v1_connections/get.java @@ -0,0 +1,7 @@ +// List connections by organization id +ListConnectionsResponse response = scalekitClient.connections( + ).listConnections(organizationId); + +// List connections by domain +ListConnectionsResponse response = scalekitClient.connections( + ).listConnectionsByDomain("your-domain.com"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_memberships_organizations_{organization_id}_users_{id}/post.java b/openapi/code_samples/java/api_v1_memberships_organizations_{organization_id}_users_{id}/post.java new file mode 100644 index 000000000..fc049148b --- /dev/null +++ b/openapi/code_samples/java/api_v1_memberships_organizations_{organization_id}_users_{id}/post.java @@ -0,0 +1,22 @@ +import com.scalekit.ScalekitClient; +import com.scalekit.api.UserClient; +import com.scalekit.grpc.scalekit.v1.users.*; +ScalekitClient scalekitClient = new ScalekitClient( + System.getenv("SCALEKIT_ENV_URL"), + System.getenv("SCALEKIT_CLIENT_ID"), + System.getenv("SCALEKIT_CLIENT_SECRET") +); +UserClient users = scalekitClient.users(); +CreateMembershipRequest membershipReq = CreateMemb + ershipRequest.newBuilder() + .setMembership( + CreateMembership.newBuilder() + .addRoles(Role.newBuilder( + ).setName("admin").build()) + .putMetadata("department", "engineering") + .putMetadata("location", "nyc-office") + .build()) + .build(); +CreateMembershipResponse res = users. + createMembership("org_123", "usr_123", + membershipReq); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations/get.java b/openapi/code_samples/java/api_v1_organizations/get.java new file mode 100644 index 000000000..95a8d773d --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations/get.java @@ -0,0 +1 @@ +ListOrganizationsResponse organizations = scalekitClient.organizations().listOrganizations(10, ""); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations/post.java b/openapi/code_samples/java/api_v1_organizations/post.java new file mode 100644 index 000000000..ca1e50c32 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations/post.java @@ -0,0 +1,5 @@ +CreateOrganization createOrganization = CreateOrganization.newBuilder() + .setDisplayName("Test Org") + .build(); + +Organization createdOrganization = scalekitClient.organizations().create(createOrganization); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{id}/delete.java b/openapi/code_samples/java/api_v1_organizations_{id}/delete.java new file mode 100644 index 000000000..59c4d43c1 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{id}/delete.java @@ -0,0 +1,7 @@ +ScalekitClient scalekitClient = new ScalekitClient( + "", + "", + "" +); + +scalekitClient.organizations().deleteById(organizationId); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{id}/get.java b/openapi/code_samples/java/api_v1_organizations_{id}/get.java new file mode 100644 index 000000000..a296d3e22 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{id}/get.java @@ -0,0 +1,7 @@ +ScalekitClient scalekitClient = new ScalekitClient( + "", + "", + "" +); + +Organization organization = scalekitClient.organizations().getById(organizationId); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{id}/patch.java b/openapi/code_samples/java/api_v1_organizations_{id}/patch.java new file mode 100644 index 000000000..f15bded87 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{id}/patch.java @@ -0,0 +1,5 @@ +UpdateOrganization updateOrganization = UpdateOrganization.newBuilder() + .setDisplayName("Updated Organization Name") + .build(); + +Organization updatedOrganizationById = scalekitClient.organizations().updateById(organizationId, updateOrganization); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{id}_portal_links/put.java b/openapi/code_samples/java/api_v1_organizations_{id}_portal_links/put.java new file mode 100644 index 000000000..3b497d7ac --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{id}_portal_links/put.java @@ -0,0 +1,3 @@ +Link portalLink = client + .organizations() + .generatePortalLink(organizationId, Arrays.asList(Feature.sso, Feature.dir_sync)); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{id}_settings/patch.java b/openapi/code_samples/java/api_v1_organizations_{id}_settings/patch.java new file mode 100644 index 000000000..24a49be6b --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{id}_settings/patch.java @@ -0,0 +1,13 @@ +OrganizationSettingsFeature featureSSO = OrganizationSettingsFeature.newBuilder() + .setName("sso") + .setEnabled(true) + .build(); + +OrganizationSettingsFeature featureDirectorySync = OrganizationSettingsFeature.newBuilder() + .setName("dir_sync") + .setEnabled(true) + .build(); + +updatedOrganization = scalekitClient.organizations() + .updateOrganizationSettings(organization.getId(), List.of(featureSSO, +featureDirectorySync)); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{org_id}_roles/get.java b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles/get.java new file mode 100644 index 000000000..d7bbdbc51 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles/get.java @@ -0,0 +1 @@ +ListOrganizationRolesResponse res = scalekitClient.roles().listOrganizationRoles("org_123"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{org_id}_roles/post.java b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles/post.java new file mode 100644 index 000000000..3aab3ce1e --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles/post.java @@ -0,0 +1,16 @@ +CreateOrganizationRoleResponse res = scalekitClient.roles().createOrganizationRole( + "org_123", + CreateOrganizationRoleRequest.newBuilder() + .setOrgId("org_123") + .setRole( + CreateOrganizationRole.newBuilder() + .setName("org_admin") + .setDisplayName("Org Admin") + .setDescription("Organization-scoped role") + .setExtends("base_role_name") // optional + .addPermissions("perm.read") // optional + .addPermissions("perm.write") // optional + .build() + ) + .build() +); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{org_id}_roles:set_defaults/patch.java b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles:set_defaults/patch.java new file mode 100644 index 000000000..6ad5e5aad --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles:set_defaults/patch.java @@ -0,0 +1,6 @@ +UpdateDefaultOrganizationRolesResponse res = scalekitClient.roles().updateDefaultOrganizationRoles( + "org_123", + UpdateDefaultOrganizationRolesRequest.newBuilder() + .setDefaultMemberRole("org_member") + .build() +); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/delete.java b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/delete.java new file mode 100644 index 000000000..b22e47a99 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/delete.java @@ -0,0 +1,5 @@ +// Basic delete +scalekitClient.roles().deleteOrganizationRole("org_123", "org_role_admin"); + +// With reassignment +scalekitClient.roles().deleteOrganizationRole("org_123", "org_role_admin", "org_role_member"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/get.java b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/get.java new file mode 100644 index 000000000..de30b4e32 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/get.java @@ -0,0 +1 @@ +GetOrganizationRoleResponse res = scalekitClient.roles().getOrganizationRole("org_123", "org_admin"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/put.java b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/put.java new file mode 100644 index 000000000..6844b2306 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/put.java @@ -0,0 +1,12 @@ +UpdateOrganizationRoleResponse res = scalekitClient.roles().updateOrganizationRole( + "org_123", + "org_admin", + UpdateOrganizationRoleRequest.newBuilder() + .setRole( + UpdateRole.newBuilder() + .setDisplayName("Org Admin (Updated)") + .setDescription("Updated org role description") + .build() + ) + .build() +); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}/delete.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}/delete.java new file mode 100644 index 000000000..c4ae1774d --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}/delete.java @@ -0,0 +1 @@ +scalekitClient.connections().deleteConnection(connectionId, organizationId); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}/get.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}/get.java new file mode 100644 index 000000000..b06590ec0 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}/get.java @@ -0,0 +1 @@ +Connection connection = scalekitClient.connections().getConnectionById(connectionId, organizationId); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.java new file mode 100644 index 000000000..59b327624 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.java @@ -0,0 +1 @@ +ToggleConnectionResponse response = scalekitClient.connections().disableConnection(connectionId, organizationId); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.java new file mode 100644 index 000000000..061134de9 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.java @@ -0,0 +1 @@ +ToggleConnectionResponse response = scalekitClient.connections().enableConnection(connectionId, organizationId); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories/get.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories/get.java new file mode 100644 index 000000000..de94a430d --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories/get.java @@ -0,0 +1 @@ +ListDirectoriesResponse response = scalekitClient.directories().listDirectories(organizationId); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.java new file mode 100644 index 000000000..92a5e88f3 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.java @@ -0,0 +1,9 @@ +var options = ListDirectoryResourceOptions.builder() + .pageSize(10) + .pageToken("") + .includeDetail(true) + .build(); + +ListDirectoryGroupsResponse groupsResponse = scalekitClient + .directories() + .listDirectoryGroups(directory.getId(), organizationId, options); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.java new file mode 100644 index 000000000..325d74863 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.java @@ -0,0 +1,9 @@ +var options = ListDirectoryResourceOptions.builder() + .pageSize(10) + .pageToken("") + .includeDetail(true) + .build(); + +ListDirectoryUsersResponse usersResponse = scalekitClient + .directories() + .listDirectoryUsers(directory.getId(), organizationId, options); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}/get.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}/get.java new file mode 100644 index 000000000..ddbcd88f9 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}/get.java @@ -0,0 +1 @@ +Directory directory = scalekitClient.directories().getDirectory(directoryId, organizationId); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.java new file mode 100644 index 000000000..6165265e3 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.java @@ -0,0 +1,3 @@ +ToggleDirectoryResponse disableResponse = scalekitClient + .directories() + .disableDirectory(directoryId, organizationId); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.java new file mode 100644 index 000000000..5cdb277c8 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.java @@ -0,0 +1,3 @@ +ToggleDirectoryResponse enableResponse = client + .directories() + .enableDirectory(directoryId, organizationId); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains/get.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains/get.java new file mode 100644 index 000000000..cc247a78d --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains/get.java @@ -0,0 +1 @@ +List domains = scalekitClient.domains().listDomainsByOrganizationId("org_id", "ORGANIZATION_DOMAIN"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains/post.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains/post.java new file mode 100644 index 000000000..082e45d88 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains/post.java @@ -0,0 +1,9 @@ +CreateDomainRequest request = CreateDomainRequest.newBuilder() + .setOrganizationId(organization.getId()) + .setDomain(CreateDomain.newBuilder() + .setDomain("example.com") + .setDomainType("ORGANIZATION_DOMAIN") + .build()) + .build(); + +Domain domain = scalekitClient.domains().createDomain(request); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains_{id}/delete.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains_{id}/delete.java new file mode 100644 index 000000000..907835521 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains_{id}/delete.java @@ -0,0 +1 @@ +scalekitClient.domains().deleteDomain(organization.getId(), domain.getId()); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains_{id}/get.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains_{id}/get.java new file mode 100644 index 000000000..536d17424 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_domains_{id}/get.java @@ -0,0 +1 @@ +Domain domain = scalekitClient.domains().getDomainById("org_123", "dom_123"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_users/get.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_users/get.java new file mode 100644 index 000000000..2db8b03ae --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_users/get.java @@ -0,0 +1,6 @@ +ListOrganizationUsersRequest listReq = ListOrganiz + ationUsersRequest.newBuilder() + .setPageSize(50) + .build(); +ListOrganizationUsersResponse list = users. + listOrganizationUsers("org_123", listReq); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_users/post.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_users/post.java new file mode 100644 index 000000000..eb0311c5f --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_users/post.java @@ -0,0 +1,18 @@ +CreateUser createUser = CreateUser.newBuilder() + .setEmail("user@example.com") + .setExternalId("ext_12345a67b89c") + .putMetadata("department", "engineering") + .putMetadata("location", "nyc-office") + .setUserProfile( + CreateUserProfile.newBuilder() + .setFirstName("John") + .setLastName("Doe") + .build()) + .build(); +CreateUserAndMembershipRequest cuReq = CreateUserA + ndMembershipRequest.newBuilder() + .setUser(createUser) + .build(); +CreateUserAndMembershipResponse cuResp = users. + createUserAndMembership("org_123", cuReq); +System.out.println(cuResp.getUser().getId()); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.java new file mode 100644 index 000000000..c38563bbc --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.java @@ -0,0 +1,2 @@ +ListUserPermissionsResponse resp = scalekitClient.users().listUserPermissions("org_123", "usr_123"); +List permissions = resp.getPermissionsList(); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.java b/openapi/code_samples/java/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.java new file mode 100644 index 000000000..74d811e36 --- /dev/null +++ b/openapi/code_samples/java/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.java @@ -0,0 +1,2 @@ +ListUserRolesResponse resp = scalekitClient.users().listUserRoles("org_123", "usr_123"); +List roles = resp.getRolesList(); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_passwordless_email_resend/post.java b/openapi/code_samples/java/api_v1_passwordless_email_resend/post.java new file mode 100644 index 000000000..b55c2a611 --- /dev/null +++ b/openapi/code_samples/java/api_v1_passwordless_email_resend/post.java @@ -0,0 +1 @@ +SendPasswordlessResponse resendResponse = passwordlessClient.resendPasswordlessEmail(authRequestId); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_passwordless_email_send/post.java b/openapi/code_samples/java/api_v1_passwordless_email_send/post.java new file mode 100644 index 000000000..434a88fac --- /dev/null +++ b/openapi/code_samples/java/api_v1_passwordless_email_send/post.java @@ -0,0 +1,18 @@ +TemplateType templateType = TemplateType.SIGNIN; +Map templateVariables = new HashMap<>(); +templateVariables.put("employeeID", "EMP523"); +templateVariables.put("teamName", "Alpha Team"); +templateVariables.put("supportEmail", "support@yourcompany.com"); + +SendPasswordlessOptions options = new SendPasswordlessOptions(); +options.setTemplate(templateType); +options.setExpiresIn(100); +options.setMagiclinkAuthUri("https://www.example.com"); +options.setTemplateVariables(templateVariables); + +SendPasswordlessResponse response = passwordlessClient.sendPasswordlessEmail( + "john.doe@example.com", + options +); + +String authRequestId = response.getAuthRequestId(); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_passwordless_email_verify/post.java b/openapi/code_samples/java/api_v1_passwordless_email_verify/post.java new file mode 100644 index 000000000..a77896808 --- /dev/null +++ b/openapi/code_samples/java/api_v1_passwordless_email_verify/post.java @@ -0,0 +1,18 @@ +// Verify with OTP code +VerifyPasswordlessOptions verifyOptions = new VerifyPasswordlessOptions(); +verifyOptions.setCode("123456"); // OTP code +verifyOptions.setAuthRequestId(authRequestId); + +VerifyPasswordLessResponse verifyResponse = passwordlessClient.verifyPasswordlessEmail(verifyOptions); + +// User verified successfully +String userEmail = verifyResponse.getEmail(); + +// Verify with magic link token +VerifyPasswordlessOptions verifyOptions = new VerifyPasswordlessOptions(); +verifyOptions.setLinkToken(linkToken); // Magic link token + +VerifyPasswordLessResponse verifyResponse = passwordlessClient.verifyPasswordlessEmail(verifyOptions); + +// User verified successfully +String userEmail = verifyResponse.getEmail(); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_permissions/get.java b/openapi/code_samples/java/api_v1_permissions/get.java new file mode 100644 index 000000000..67506a367 --- /dev/null +++ b/openapi/code_samples/java/api_v1_permissions/get.java @@ -0,0 +1 @@ +ListPermissionsResponse res = scalekitClient.permissions().listPermissions(); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_permissions/post.java b/openapi/code_samples/java/api_v1_permissions/post.java new file mode 100644 index 000000000..a4a2e3049 --- /dev/null +++ b/openapi/code_samples/java/api_v1_permissions/post.java @@ -0,0 +1,10 @@ +CreatePermissionResponse res = scalekitClient.permissions().createPermission( + CreatePermissionRequest.newBuilder() + .setPermission( + CreatePermission.newBuilder() + .setName("read:users") + .setDescription("Allows reading users") + .build() + ) + .build() +); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_permissions_{permission_name}/delete.java b/openapi/code_samples/java/api_v1_permissions_{permission_name}/delete.java new file mode 100644 index 000000000..1b8f6319a --- /dev/null +++ b/openapi/code_samples/java/api_v1_permissions_{permission_name}/delete.java @@ -0,0 +1 @@ +scalekitClient.permissions().deletePermission("read:users"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_permissions_{permission_name}/get.java b/openapi/code_samples/java/api_v1_permissions_{permission_name}/get.java new file mode 100644 index 000000000..2b1dd3552 --- /dev/null +++ b/openapi/code_samples/java/api_v1_permissions_{permission_name}/get.java @@ -0,0 +1 @@ +GetPermissionResponse res = scalekitClient.permissions().getPermission("read:users"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_permissions_{permission_name}/put.java b/openapi/code_samples/java/api_v1_permissions_{permission_name}/put.java new file mode 100644 index 000000000..8dd133ba4 --- /dev/null +++ b/openapi/code_samples/java/api_v1_permissions_{permission_name}/put.java @@ -0,0 +1,11 @@ +UpdatePermissionResponse res = scalekitClient.permissions().updatePermission( + "read:users", + UpdatePermissionRequest.newBuilder() + .setPermission( + CreatePermission.newBuilder() + .setName("read:users") + .setDescription("Allows reading user resources") + .build() + ) + .build() +); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_roles/get.java b/openapi/code_samples/java/api_v1_roles/get.java new file mode 100644 index 000000000..8c8e9cf81 --- /dev/null +++ b/openapi/code_samples/java/api_v1_roles/get.java @@ -0,0 +1 @@ +ListRolesResponse res = scalekitClient.roles().listRoles(); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_roles/post.java b/openapi/code_samples/java/api_v1_roles/post.java new file mode 100644 index 000000000..244afad2b --- /dev/null +++ b/openapi/code_samples/java/api_v1_roles/post.java @@ -0,0 +1,13 @@ +CreateRoleResponse res = scalekitClient.roles().createRole( + CreateRoleRequest.newBuilder() + .setRole( + CreateRole.newBuilder() + .setName("admin") + .setDisplayName("Admin") + .setDescription("Environment-level role") + // .setExtends("base_role") // optional + // .addPermissions("read:users") // optional + .build() + ) + .build() +); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_roles:set_defaults/patch.java b/openapi/code_samples/java/api_v1_roles:set_defaults/patch.java new file mode 100644 index 000000000..bf87123a6 --- /dev/null +++ b/openapi/code_samples/java/api_v1_roles:set_defaults/patch.java @@ -0,0 +1,5 @@ +UpdateDefaultRolesResponse res = scalekitClient.roles().updateDefaultRoles( + UpdateDefaultRolesRequest.newBuilder() + .setDefaultMemberRole("member") + .build() +); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_roles_{role_name}/delete.java b/openapi/code_samples/java/api_v1_roles_{role_name}/delete.java new file mode 100644 index 000000000..d2f42b8d7 --- /dev/null +++ b/openapi/code_samples/java/api_v1_roles_{role_name}/delete.java @@ -0,0 +1,5 @@ +// Basic delete +scalekitClient.roles().deleteRole("admin"); + +// With reassignment +scalekitClient.roles().deleteRole("admin", "member"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_roles_{role_name}/get.java b/openapi/code_samples/java/api_v1_roles_{role_name}/get.java new file mode 100644 index 000000000..bc9607567 --- /dev/null +++ b/openapi/code_samples/java/api_v1_roles_{role_name}/get.java @@ -0,0 +1 @@ +GetRoleResponse res = scalekitClient.roles().getRole("admin"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_roles_{role_name}/put.java b/openapi/code_samples/java/api_v1_roles_{role_name}/put.java new file mode 100644 index 000000000..74e1fe62c --- /dev/null +++ b/openapi/code_samples/java/api_v1_roles_{role_name}/put.java @@ -0,0 +1,11 @@ +UpdateRoleResponse res = scalekitClient.roles().updateRole( + "admin", + UpdateRoleRequest.newBuilder() + .setRole( + UpdateRole.newBuilder() + .setDisplayName("Admin (Updated)") + .setDescription("Updated description") + .build() + ) + .build() +); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_roles_{role_name}_dependents/get.java b/openapi/code_samples/java/api_v1_roles_{role_name}_dependents/get.java new file mode 100644 index 000000000..e1dfffecd --- /dev/null +++ b/openapi/code_samples/java/api_v1_roles_{role_name}_dependents/get.java @@ -0,0 +1 @@ +ListDependentRolesResponse res = scalekitClient.roles().listDependentRoles("admin"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_roles_{role_name}_permissions/get.java b/openapi/code_samples/java/api_v1_roles_{role_name}_permissions/get.java new file mode 100644 index 000000000..95f9604a1 --- /dev/null +++ b/openapi/code_samples/java/api_v1_roles_{role_name}_permissions/get.java @@ -0,0 +1 @@ +ListRolePermissionsResponse res = scalekitClient.permissions().listRolePermissions("admin"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_roles_{role_name}_permissions/post.java b/openapi/code_samples/java/api_v1_roles_{role_name}_permissions/post.java new file mode 100644 index 000000000..2cf6d9113 --- /dev/null +++ b/openapi/code_samples/java/api_v1_roles_{role_name}_permissions/post.java @@ -0,0 +1,7 @@ +AddPermissionsToRoleResponse res = scalekitClient.permissions().addPermissionsToRole( + "role_admin", + AddPermissionsToRoleRequest.newBuilder() + .addPermissionNames("perm.read") + .addPermissionNames("perm.write") + .build() +); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_roles_{role_name}_permissions_{permission_name}/delete.java b/openapi/code_samples/java/api_v1_roles_{role_name}_permissions_{permission_name}/delete.java new file mode 100644 index 000000000..c804a404d --- /dev/null +++ b/openapi/code_samples/java/api_v1_roles_{role_name}_permissions_{permission_name}/delete.java @@ -0,0 +1 @@ +scalekitClient.permissions().removePermissionFromRole("admin", "read:users"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_roles_{role_name}_users:count/get.java b/openapi/code_samples/java/api_v1_roles_{role_name}_users:count/get.java new file mode 100644 index 000000000..916e222d7 --- /dev/null +++ b/openapi/code_samples/java/api_v1_roles_{role_name}_users:count/get.java @@ -0,0 +1 @@ +GetRoleUsersCountResponse res = scalekitClient.roles().getRoleUsersCount("admin"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_sessions_{session_id}/get.java b/openapi/code_samples/java/api_v1_sessions_{session_id}/get.java new file mode 100644 index 000000000..8444ad0d1 --- /dev/null +++ b/openapi/code_samples/java/api_v1_sessions_{session_id}/get.java @@ -0,0 +1 @@ +SessionDetails res = scalekitClient.sessions().getSession("ses_123456789"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_sessions_{session_id}_revoke/post.java b/openapi/code_samples/java/api_v1_sessions_{session_id}_revoke/post.java new file mode 100644 index 000000000..6a1afbcc5 --- /dev/null +++ b/openapi/code_samples/java/api_v1_sessions_{session_id}_revoke/post.java @@ -0,0 +1 @@ +RevokeSessionResponse res = scalekitClient.sessions().revokeSession("ses_123456789"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_users/get.java b/openapi/code_samples/java/api_v1_users/get.java new file mode 100644 index 000000000..5f51daef4 --- /dev/null +++ b/openapi/code_samples/java/api_v1_users/get.java @@ -0,0 +1,3 @@ +ListUsersRequest lur = ListUsersRequest. + newBuilder().setPageSize(100).build(); +ListUsersResponse allUsers = users.listUsers(lur); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_users_{id}/delete.java b/openapi/code_samples/java/api_v1_users_{id}/delete.java new file mode 100644 index 000000000..ad44101d3 --- /dev/null +++ b/openapi/code_samples/java/api_v1_users_{id}/delete.java @@ -0,0 +1 @@ +users.deleteUser("usr_123"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_users_{id}/get.java b/openapi/code_samples/java/api_v1_users_{id}/get.java new file mode 100644 index 000000000..5035ec171 --- /dev/null +++ b/openapi/code_samples/java/api_v1_users_{id}/get.java @@ -0,0 +1,2 @@ +GetUserResponse resp = scalekitClient.users().getUser("usr_123456"); +User user = resp.getUser(); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_users_{id}/patch.java b/openapi/code_samples/java/api_v1_users_{id}/patch.java new file mode 100644 index 000000000..fb851b284 --- /dev/null +++ b/openapi/code_samples/java/api_v1_users_{id}/patch.java @@ -0,0 +1,11 @@ +UpdateUser upd = UpdateUser.newBuilder() + .setUserProfile( + UpdateUserProfile.newBuilder() + .setFirstName("John") + .setLastName("Smith") + .build()) + .putMetadata("department", "sales") + .build(); +UpdateUserRequest updReq = UpdateUserRequest. + newBuilder().setUser(upd).build(); +users.updateUser("usr_123", updReq); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_users_{user_id}_sessions/get.java b/openapi/code_samples/java/api_v1_users_{user_id}_sessions/get.java new file mode 100644 index 000000000..5446b24d6 --- /dev/null +++ b/openapi/code_samples/java/api_v1_users_{user_id}_sessions/get.java @@ -0,0 +1,11 @@ +// Basic usage +UserSessionDetails res = scalekitClient.sessions().getUserSessions("user_123", null, null, null); + +// With pagination and filtering +// import UserSessionFilter, Timestamp, Instant +UserSessionFilter filter = UserSessionFilter.newBuilder() + .addStatus("ACTIVE") + .setStartTime(Timestamp.newBuilder().setSeconds(Instant.parse("2024-01-01T00:00:00Z").getEpochSecond()).build()) + .setEndTime(Timestamp.newBuilder().setSeconds(Instant.parse("2024-12-31T23:59:59Z").getEpochSecond()).build()) + .build(); +UserSessionDetails res = scalekitClient.sessions().getUserSessions("user_123", 10, "next_page_token", filter); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_users_{user_id}_sessions_revoke/post.java b/openapi/code_samples/java/api_v1_users_{user_id}_sessions_revoke/post.java new file mode 100644 index 000000000..420c65bd6 --- /dev/null +++ b/openapi/code_samples/java/api_v1_users_{user_id}_sessions_revoke/post.java @@ -0,0 +1 @@ +RevokeAllUserSessionsResponse res = scalekitClient.sessions().revokeAllUserSessions("user_123"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_webauthn_credentials/get.java b/openapi/code_samples/java/api_v1_webauthn_credentials/get.java new file mode 100644 index 000000000..f924d0919 --- /dev/null +++ b/openapi/code_samples/java/api_v1_webauthn_credentials/get.java @@ -0,0 +1 @@ +ListCredentialsResponse res = scalekitClient.webauthn().listCredentials("user_123"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_webauthn_credentials_{credential_id}/delete.java b/openapi/code_samples/java/api_v1_webauthn_credentials_{credential_id}/delete.java new file mode 100644 index 000000000..7f851f325 --- /dev/null +++ b/openapi/code_samples/java/api_v1_webauthn_credentials_{credential_id}/delete.java @@ -0,0 +1 @@ +DeleteCredentialResponse res = scalekitClient.webauthn().deleteCredential("wac_123"); \ No newline at end of file diff --git a/openapi/code_samples/java/api_v1_webauthn_credentials_{credential_id}/patch.java b/openapi/code_samples/java/api_v1_webauthn_credentials_{credential_id}/patch.java new file mode 100644 index 000000000..7977f57e2 --- /dev/null +++ b/openapi/code_samples/java/api_v1_webauthn_credentials_{credential_id}/patch.java @@ -0,0 +1,2 @@ +UpdateCredentialResponse res = scalekitClient.webauthn() + .updateCredential("wac_123", "Work Laptop Passkey"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_connections/get.js b/openapi/code_samples/javascript/api_v1_connections/get.js new file mode 100644 index 000000000..189b5d6fd --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_connections/get.js @@ -0,0 +1,5 @@ +// List connections by organization id +const connections = await scalekit.connection.listConnections(organizationId); + +// List connections by domain +const connections = await scalekit.connection.listConnectionsByDomain(domain); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_memberships_organizations_{organization_id}_users_{id}/post.js b/openapi/code_samples/javascript/api_v1_memberships_organizations_{organization_id}_users_{id}/post.js new file mode 100644 index 000000000..41c7f58dd --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_memberships_organizations_{organization_id}_users_{id}/post.js @@ -0,0 +1,13 @@ +import { ScalekitClient } from "@scalekit-sdk/node"; +const scalekit = new ScalekitClient( + process.env.SCALEKIT_ENV_URL, + process.env.SCALEKIT_CLIENT_ID, + process.env.SCALEKIT_CLIENT_SECRET +); +await scalekit.user.createMembership("org_123", "usr_123", { + roles: ["admin"], + metadata: { + department: "engineering", + location: "nyc-office", + }, +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations/get.js b/openapi/code_samples/javascript/api_v1_organizations/get.js new file mode 100644 index 000000000..a1536a0ea --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations/get.js @@ -0,0 +1,3 @@ +const organizations = await scalekit.organization.listOrganization({ + pageSize: 10, +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations/post.js b/openapi/code_samples/javascript/api_v1_organizations/post.js new file mode 100644 index 000000000..06f259945 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations/post.js @@ -0,0 +1,5 @@ +const organization = await scalekit.organization.createOrganization(name, { + + externalId: "externalId", + +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{id}/delete.js b/openapi/code_samples/javascript/api_v1_organizations_{id}/delete.js new file mode 100644 index 000000000..d4979bb48 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{id}/delete.js @@ -0,0 +1 @@ +await scalekit.organization.deleteOrganization(organizationId); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{id}/get.js b/openapi/code_samples/javascript/api_v1_organizations_{id}/get.js new file mode 100644 index 000000000..d5312ba8f --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{id}/get.js @@ -0,0 +1,7 @@ +const scalekit = new ScalekitClient( + , + , + +); + +const organization = await scalekit.organization.getOrganization(organization_id); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{id}/patch.js b/openapi/code_samples/javascript/api_v1_organizations_{id}/patch.js new file mode 100644 index 000000000..91173f31d --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{id}/patch.js @@ -0,0 +1,4 @@ +const organization = await scalekit.organization.updateOrganization(organization_id, { + displayName: 'displayName', + externalId: 'externalId', +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{id}_portal_links/put.js b/openapi/code_samples/javascript/api_v1_organizations_{id}_portal_links/put.js new file mode 100644 index 000000000..7f494a458 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{id}_portal_links/put.js @@ -0,0 +1 @@ +const link = await scalekit.organization.generatePortalLink(organizationId); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{id}_settings/patch.js b/openapi/code_samples/javascript/api_v1_organizations_{id}_settings/patch.js new file mode 100644 index 000000000..434b0a10a --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{id}_settings/patch.js @@ -0,0 +1,14 @@ +const settings = { + features: [ + { + name: 'sso', + enabled: true, + }, + { + name: 'dir_sync', + enabled: true, + }, + ], +}; + +await scalekit.organization.updateOrganizationSettings('', settings); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles/get.js b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles/get.js new file mode 100644 index 000000000..95545a870 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles/get.js @@ -0,0 +1 @@ +const res = await scalekit.role.listOrganizationRoles("org_123"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles/post.js b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles/post.js new file mode 100644 index 000000000..8d7ea86b1 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles/post.js @@ -0,0 +1,7 @@ +await scalekit.role.createOrganizationRole("org_123", { + name: "org_admin", + displayName: "Org Admin", + description: "Organization-scoped role", + extends: "base_role_name", // optional + permissions: ["perm.read", "perm.write"] // optional +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles:set_defaults/patch.js b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles:set_defaults/patch.js new file mode 100644 index 000000000..7b94a1239 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles:set_defaults/patch.js @@ -0,0 +1,3 @@ +const res = await scalekit.role.updateDefaultOrganizationRoles("org_123", { + defaultMemberRole: "org_member" +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/delete.js b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/delete.js new file mode 100644 index 000000000..1fedbc835 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/delete.js @@ -0,0 +1,5 @@ +// Basic delete +await scalekit.role.deleteOrganizationRole("org_123", "org_role_admin"); + +// With reassignment +await scalekit.role.deleteOrganizationRole("org_123", "org_role_admin", "org_role_member"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/get.js b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/get.js new file mode 100644 index 000000000..ae77d7b72 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/get.js @@ -0,0 +1 @@ +const res = await scalekit.role.getOrganizationRole("org_123", "org_admin"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/put.js b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/put.js new file mode 100644 index 000000000..158cc8b6f --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/put.js @@ -0,0 +1,4 @@ +await scalekit.role.updateOrganizationRole("org_123", "org_admin", { + displayName: "Org Admin (Updated)", + description: "Updated org role description" +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}/delete.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}/delete.js new file mode 100644 index 000000000..fd99c27df --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}/delete.js @@ -0,0 +1 @@ +await scalekit.connection.deleteConnection(organizationId, connectionId); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}/get.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}/get.js new file mode 100644 index 000000000..8a74d8a56 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}/get.js @@ -0,0 +1,4 @@ +const connection = await scalekit.connection.getConnection( + organizationId, + connectionId +); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.js new file mode 100644 index 000000000..965b901ab --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.js @@ -0,0 +1 @@ +await scalekit.connection.disableConnection(organizationId, connectionId); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.js new file mode 100644 index 000000000..4767aeda3 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.js @@ -0,0 +1 @@ +await scalekit.connection.enableConnection(organizationId, connectionId); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories/get.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories/get.js new file mode 100644 index 000000000..1055c7e94 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories/get.js @@ -0,0 +1 @@ +await scalekit.directory.listDirectories(''); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.js new file mode 100644 index 000000000..d1dff2a72 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.js @@ -0,0 +1,4 @@ +const { groups } = await scalekit.directory.listDirectoryGroups( + '', + '' +); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.js new file mode 100644 index 000000000..1abf88acc --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.js @@ -0,0 +1,4 @@ +const { users } = await scalekit.directory.listDirectoryUsers( + '', + '' +); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}/get.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}/get.js new file mode 100644 index 000000000..7e71af729 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}/get.js @@ -0,0 +1,4 @@ +const { directory } = await scalekit.directory.getDirectory( + organizationId, + directoryId +); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.js new file mode 100644 index 000000000..8792268bb --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.js @@ -0,0 +1,4 @@ +await scalekit.directory.disableDirectory( + '', + '' +); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.js new file mode 100644 index 000000000..1010f8fe6 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.js @@ -0,0 +1 @@ +await scalekit.directory.enableDirectory('', ''); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains/get.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains/get.js new file mode 100644 index 000000000..2ab43cae2 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains/get.js @@ -0,0 +1,10 @@ +// List all domains in an organization +const response = await scalekit.domain.listDomains(organizationId, { + domainType: "ORGANIZATION_DOMAIN" +}); + +// Domain object contains: +// - id: Domain identifier +// - domain: Domain name +// - organizationId: Owning organization +// - domainType: Configuration type \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains/post.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains/post.js new file mode 100644 index 000000000..fcad5153a --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains/post.js @@ -0,0 +1,8 @@ +// Add a new domain to an organization +const response = await scalekit.createDomain("org-123", "example.com", { + + // Domain type: controls user authentication and email validation + + domainType: "ORGANIZATION_DOMAIN", + +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains_{id}/delete.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains_{id}/delete.js new file mode 100644 index 000000000..b48da72f5 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains_{id}/delete.js @@ -0,0 +1,3 @@ +// Remove a domain from an organization +// Caution: Deletion is permanent and may affect user access +const response = await scalekit.domain.deleteDomain(organizationId, domainId); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains_{id}/get.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains_{id}/get.js new file mode 100644 index 000000000..0be598555 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_domains_{id}/get.js @@ -0,0 +1,8 @@ +// Fetch details of a specific domain +const response = await scalekit.domain.getDomain(organizationId, domainId); + +// Domain object properties: +// - id: Domain identifier +// - domain: Domain name +// - organizationId: Owning organization +// - domainType: Domain configuration type \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users/get.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users/get.js new file mode 100644 index 000000000..dc4bcd998 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users/get.js @@ -0,0 +1,5 @@ +const response = await scalekit.user. + listOrganizationUsers("org_123", { + pageSize: 50, +}); +console.log(response.users); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users/post.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users/post.js new file mode 100644 index 000000000..709063cd5 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users/post.js @@ -0,0 +1,12 @@ +const { + user } = await scalekit.user. + createUserAndMembership("org_123", { + email: "user@example.com", + externalId: "ext_12345a67b89c", + metadata: { department: "engineering", + location: "nyc-office" }, + userProfile: { + firstName: "John", + lastName: "Doe", + }, +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.js new file mode 100644 index 000000000..06c92cfbe --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.js @@ -0,0 +1 @@ +const { permissions } = await scalekit.user.listUserPermissions("org_123", "usr_123"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.js b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.js new file mode 100644 index 000000000..f0aee56db --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.js @@ -0,0 +1 @@ +const { roles } = await scalekit.user.listUserRoles("org_123", "usr_123"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_passwordless_email_resend/post.js b/openapi/code_samples/javascript/api_v1_passwordless_email_resend/post.js new file mode 100644 index 000000000..2a1a22e22 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_passwordless_email_resend/post.js @@ -0,0 +1,6 @@ +const { authRequestId } = sendResponse; +const resendResponse = await scalekit.passwordless.resendPasswordlessEmail( + + authRequestId + +); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_passwordless_email_send/post.js b/openapi/code_samples/javascript/api_v1_passwordless_email_send/post.js new file mode 100644 index 000000000..da1d521fe --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_passwordless_email_send/post.js @@ -0,0 +1,13 @@ +const response = await scalekit.passwordless.sendPasswordlessEmail( + "john.doe@example.com", + { + template: "SIGNIN", + expiresIn: 100, + magiclinkAuthUri: "https://www.google.com", + templateVariables: { + employeeID: "EMP523", + teamName: "Alpha Team", + supportEmail: "support@yourcompany.com", + }, + } +); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_passwordless_email_verify/post.js b/openapi/code_samples/javascript/api_v1_passwordless_email_verify/post.js new file mode 100644 index 000000000..e313910ae --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_passwordless_email_verify/post.js @@ -0,0 +1,14 @@ +const { authRequestId } = sendResponse; +const verifyResponse = await scalekit.passwordless.verifyPasswordlessEmail( + + // Verification Code (OTP) + + { code: "123456" }, + + // Magic Link Token + + { linkToken: link_token }, + + authRequestId + +); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_permissions/get.js b/openapi/code_samples/javascript/api_v1_permissions/get.js new file mode 100644 index 000000000..f5200df33 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_permissions/get.js @@ -0,0 +1 @@ +const res = await scalekit.permission.listPermissions(); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_permissions/post.js b/openapi/code_samples/javascript/api_v1_permissions/post.js new file mode 100644 index 000000000..907acd375 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_permissions/post.js @@ -0,0 +1,4 @@ +await scalekit.permission.createPermission({ + name: "read:users", + description: "Allows reading users" +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_permissions_{permission_name}/delete.js b/openapi/code_samples/javascript/api_v1_permissions_{permission_name}/delete.js new file mode 100644 index 000000000..1daa686da --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_permissions_{permission_name}/delete.js @@ -0,0 +1 @@ +await scalekit.permission.deletePermission("read:users"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_permissions_{permission_name}/get.js b/openapi/code_samples/javascript/api_v1_permissions_{permission_name}/get.js new file mode 100644 index 000000000..e6b68a06e --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_permissions_{permission_name}/get.js @@ -0,0 +1 @@ +const res = await scalekit.permission.getPermission("read:users"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_permissions_{permission_name}/put.js b/openapi/code_samples/javascript/api_v1_permissions_{permission_name}/put.js new file mode 100644 index 000000000..ce0a30657 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_permissions_{permission_name}/put.js @@ -0,0 +1,4 @@ +await scalekit.permission.updatePermission("read:users", { + name: "read:users", + description: "Allows reading user resources" +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_roles/get.js b/openapi/code_samples/javascript/api_v1_roles/get.js new file mode 100644 index 000000000..cef04c487 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_roles/get.js @@ -0,0 +1 @@ +const res = await scalekit.role.listRoles(); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_roles/post.js b/openapi/code_samples/javascript/api_v1_roles/post.js new file mode 100644 index 000000000..9d7e51ada --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_roles/post.js @@ -0,0 +1,7 @@ +await scalekit.role.createRole({ + name: "admin", + displayName: "Admin", + description: "Environment-level role", + extends: "base_role", // optional + permissions: ["read:users"] // optional +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_roles:set_defaults/patch.js b/openapi/code_samples/javascript/api_v1_roles:set_defaults/patch.js new file mode 100644 index 000000000..d1d4b6765 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_roles:set_defaults/patch.js @@ -0,0 +1,3 @@ +const res = await scalekit.role.updateDefaultRoles({ + defaultMemberRole: "member" +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_roles_{role_name}/delete.js b/openapi/code_samples/javascript/api_v1_roles_{role_name}/delete.js new file mode 100644 index 000000000..f9015c2c4 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_roles_{role_name}/delete.js @@ -0,0 +1,5 @@ +// Basic delete +await scalekit.role.deleteRole("admin"); + +// With reassignment +await scalekit.role.deleteRole("admin", "member"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_roles_{role_name}/get.js b/openapi/code_samples/javascript/api_v1_roles_{role_name}/get.js new file mode 100644 index 000000000..f2083053f --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_roles_{role_name}/get.js @@ -0,0 +1 @@ +const res = await scalekit.role.getRole("admin"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_roles_{role_name}/put.js b/openapi/code_samples/javascript/api_v1_roles_{role_name}/put.js new file mode 100644 index 000000000..d21fc8c22 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_roles_{role_name}/put.js @@ -0,0 +1,4 @@ +await scalekit.role.updateRole("admin", { + displayName: "Admin (Updated)", + description: "Updated description" +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_roles_{role_name}_dependents/get.js b/openapi/code_samples/javascript/api_v1_roles_{role_name}_dependents/get.js new file mode 100644 index 000000000..f36221645 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_roles_{role_name}_dependents/get.js @@ -0,0 +1 @@ +const res = await scalekit.role.listDependentRoles("admin"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions/get.js b/openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions/get.js new file mode 100644 index 000000000..b75c9e0e7 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions/get.js @@ -0,0 +1 @@ +const res = await scalekit.permission.listRolePermissions("admin"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions/post.js b/openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions/post.js new file mode 100644 index 000000000..360c2159f --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions/post.js @@ -0,0 +1 @@ +await scalekit.permission.addPermissionsToRole("role_admin", ["perm.read", "perm.write"]); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions_{permission_name}/delete.js b/openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions_{permission_name}/delete.js new file mode 100644 index 000000000..f3e45bf90 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_roles_{role_name}_permissions_{permission_name}/delete.js @@ -0,0 +1 @@ +await scalekit.permission.removePermissionFromRole("admin", "read:users"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_roles_{role_name}_users:count/get.js b/openapi/code_samples/javascript/api_v1_roles_{role_name}_users:count/get.js new file mode 100644 index 000000000..4ad8ad596 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_roles_{role_name}_users:count/get.js @@ -0,0 +1 @@ +const res = await scalekit.role.getRoleUsersCount("admin"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_sessions_{session_id}/get.js b/openapi/code_samples/javascript/api_v1_sessions_{session_id}/get.js new file mode 100644 index 000000000..fe7cb5c0d --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_sessions_{session_id}/get.js @@ -0,0 +1 @@ +const res = await scalekit.session.getSession("ses_123456789"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_sessions_{session_id}_revoke/post.js b/openapi/code_samples/javascript/api_v1_sessions_{session_id}_revoke/post.js new file mode 100644 index 000000000..ac910fa01 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_sessions_{session_id}_revoke/post.js @@ -0,0 +1 @@ +const res = await scalekit.session.revokeSession("ses_123456789"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_users/get.js b/openapi/code_samples/javascript/api_v1_users/get.js new file mode 100644 index 000000000..3b7b9bc7f --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_users/get.js @@ -0,0 +1,2 @@ +const response = await scalekit.user.listUsers( + { pageSize: 100 }); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_users_{id}/delete.js b/openapi/code_samples/javascript/api_v1_users_{id}/delete.js new file mode 100644 index 000000000..47827b71d --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_users_{id}/delete.js @@ -0,0 +1 @@ +await scalekit.user.deleteUser("usr_123"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_users_{id}/get.js b/openapi/code_samples/javascript/api_v1_users_{id}/get.js new file mode 100644 index 000000000..3d817f27c --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_users_{id}/get.js @@ -0,0 +1 @@ +const { user } = await scalekit.user.getUser("usr_123456"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_users_{id}/patch.js b/openapi/code_samples/javascript/api_v1_users_{id}/patch.js new file mode 100644 index 000000000..b0961523a --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_users_{id}/patch.js @@ -0,0 +1,9 @@ +await scalekit.user.updateUser("usr_123", { + userProfile: { + firstName: "John", + lastName: "Smith", + }, + metadata: { + department: "sales", + }, +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_users_{user_id}_sessions/get.js b/openapi/code_samples/javascript/api_v1_users_{user_id}_sessions/get.js new file mode 100644 index 000000000..68f7b2fb5 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_users_{user_id}_sessions/get.js @@ -0,0 +1,13 @@ +// Basic usage +const res = await scalekit.session.getUserSessions("user_123"); + +// With pagination and filtering +const res = await scalekit.session.getUserSessions("user_123", { + pageSize: 10, + pageToken: "next_page_token", + filter: { + status: ["ACTIVE"], + startTime: new Date("2024-01-01"), + endTime: new Date("2024-12-31") + } +}); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_users_{user_id}_sessions_revoke/post.js b/openapi/code_samples/javascript/api_v1_users_{user_id}_sessions_revoke/post.js new file mode 100644 index 000000000..df6e80d6b --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_users_{user_id}_sessions_revoke/post.js @@ -0,0 +1 @@ +const res = await scalekit.session.revokeAllUserSessions("user_123"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_webauthn_credentials/get.js b/openapi/code_samples/javascript/api_v1_webauthn_credentials/get.js new file mode 100644 index 000000000..12d2e9e53 --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_webauthn_credentials/get.js @@ -0,0 +1 @@ +const res = await scalekit.webauthn.listCredentials("user_123"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_webauthn_credentials_{credential_id}/delete.js b/openapi/code_samples/javascript/api_v1_webauthn_credentials_{credential_id}/delete.js new file mode 100644 index 000000000..8318726dd --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_webauthn_credentials_{credential_id}/delete.js @@ -0,0 +1 @@ +const res = await scalekit.webauthn.deleteCredential("wac_123"); \ No newline at end of file diff --git a/openapi/code_samples/javascript/api_v1_webauthn_credentials_{credential_id}/patch.js b/openapi/code_samples/javascript/api_v1_webauthn_credentials_{credential_id}/patch.js new file mode 100644 index 000000000..daa03e55e --- /dev/null +++ b/openapi/code_samples/javascript/api_v1_webauthn_credentials_{credential_id}/patch.js @@ -0,0 +1,4 @@ +const res = await scalekit.webauthn.updateCredential( + "wac_123", + "Work Laptop Passkey" +); \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_connections/get.py b/openapi/code_samples/python/api_v1_connections/get.py new file mode 100644 index 000000000..62533de66 --- /dev/null +++ b/openapi/code_samples/python/api_v1_connections/get.py @@ -0,0 +1,7 @@ +# List connections by organization id +connections = scalekit_client.connection.list_connections( + organization_id +) + +# List connections by domain +response = scalekit_client.connection.list_connections_by_domain(domain="example.com") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_memberships_organizations_{organization_id}_users_{id}/delete.py b/openapi/code_samples/python/api_v1_memberships_organizations_{organization_id}_users_{id}/delete.py new file mode 100644 index 000000000..2a6f7b3cd --- /dev/null +++ b/openapi/code_samples/python/api_v1_memberships_organizations_{organization_id}_users_{id}/delete.py @@ -0,0 +1,3 @@ +response = scalekit_client.users.delete_membership( + organization_id=org_id,user_id=user_id +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_memberships_organizations_{organization_id}_users_{id}/post.py b/openapi/code_samples/python/api_v1_memberships_organizations_{organization_id}_users_{id}/post.py new file mode 100644 index 000000000..ddff07773 --- /dev/null +++ b/openapi/code_samples/python/api_v1_memberships_organizations_{organization_id}_users_{id}/post.py @@ -0,0 +1,12 @@ +from scalekit.v1.users.users_pb2 import CreateMembership +from scalekit.v1.commons.commons_pb2 import Role + +membership = CreateMembership( + roles=[Role(name="admin")], + metadata={"department": "engineering", "location": "nyc-office"}, +) +resp = scalekit_client.users.create_membership( + organization_id="org_123", + user_id="usr_123", + membership=membership, +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations/get.py b/openapi/code_samples/python/api_v1_organizations/get.py new file mode 100644 index 000000000..63baa6c48 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations/get.py @@ -0,0 +1,6 @@ +options = ListOrganizationOptions() +options.page_size = 10 + +organizations = scalekit_client.organization.list_organizations( + options=options +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations/post.py b/openapi/code_samples/python/api_v1_organizations/post.py new file mode 100644 index 000000000..e833017b5 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations/post.py @@ -0,0 +1,6 @@ +options = CreateOrganizationOptions() +options.external_id = "externalId" +organization = scalekit_client.organization.create_organization( + name, + options=options +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{id}/delete.py b/openapi/code_samples/python/api_v1_organizations_{id}/delete.py new file mode 100644 index 000000000..5d71d58f1 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{id}/delete.py @@ -0,0 +1 @@ +scalekit_client.organization.delete_organization(organization_id) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{id}/get.py b/openapi/code_samples/python/api_v1_organizations_{id}/get.py new file mode 100644 index 000000000..b7bd8f4ef --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{id}/get.py @@ -0,0 +1,9 @@ +scalekit_client = ScalekitClient( + , + , + +) + +organization = scalekit_client.organization.get_organization( + organization_id +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{id}/patch.py b/openapi/code_samples/python/api_v1_organizations_{id}/patch.py new file mode 100644 index 000000000..4fe3eba6b --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{id}/patch.py @@ -0,0 +1,4 @@ +organization = scalekit_client.organization.update_organization(organization_id, { + display_name: "display_name", + external_id: "external_id" +}) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{id}_portal_links/put.py b/openapi/code_samples/python/api_v1_organizations_{id}_portal_links/put.py new file mode 100644 index 000000000..d5ceae6e8 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{id}_portal_links/put.py @@ -0,0 +1,3 @@ +link = scalekit_client.organization.generate_portal_link( + organization_id +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{id}_settings/patch.py b/openapi/code_samples/python/api_v1_organizations_{id}_settings/patch.py new file mode 100644 index 000000000..4273b7d88 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{id}_settings/patch.py @@ -0,0 +1,14 @@ +settings = [ + { + "name": "sso", + "enabled": True + }, + { + "name": "dir_sync", + "enabled": True + } + ] + +scalekit_client.organization.update_organization_settings( + organization_id='', settings=settings +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{org_id}_roles/get.py b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles/get.py new file mode 100644 index 000000000..3897b1768 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles/get.py @@ -0,0 +1 @@ +res = scalekit_client.roles.list_organization_roles(org_id="org_123") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{org_id}_roles/post.py b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles/post.py new file mode 100644 index 000000000..7f7adbd1e --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles/post.py @@ -0,0 +1,14 @@ +from scalekit.v1.roles.roles_pb2 import CreateOrganizationRole + +role = CreateOrganizationRole( + name="org_admin", + display_name="Org Admin", + description="Organization-scoped role", + extends="base_role_name", # optional + permissions=["perm.read", "perm.write"] # optional +) + +scalekit_client.roles.create_organization_role( + org_id="org_123", + role=role +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{org_id}_roles:set_defaults/patch.py b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles:set_defaults/patch.py new file mode 100644 index 000000000..0c3d3c21c --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles:set_defaults/patch.py @@ -0,0 +1,8 @@ +from scalekit.v1.roles.roles_pb2 import UpdateDefaultOrganizationRolesRequest + +res = scalekit_client.roles.update_default_organization_roles( + org_id="org_123", + default_roles=UpdateDefaultOrganizationRolesRequest( + default_member_role="org_member" + ) +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/delete.py b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/delete.py new file mode 100644 index 000000000..af2a74c15 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/delete.py @@ -0,0 +1,12 @@ +# Basic delete +scalekit_client.roles.delete_organization_role( + org_id="org_123", + role_name="org_role_admin" +) + +# With reassignment +scalekit_client.roles.delete_organization_role( + org_id="org_123", + role_name="org_role_admin", + reassign_role_name="org_role_member" +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/get.py b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/get.py new file mode 100644 index 000000000..c718f0c37 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/get.py @@ -0,0 +1,4 @@ +res = scalekit_client.roles.get_organization_role( + org_id="org_123", + role_name="org_admin" +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/put.py b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/put.py new file mode 100644 index 000000000..92c37d7a3 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/put.py @@ -0,0 +1,10 @@ +from scalekit.v1.roles.roles_pb2 import UpdateRole + +scalekit_client.roles.update_organization_role( + org_id="org_123", + role_name="org_admin", + role=UpdateRole( + display_name="Org Admin (Updated)", + description="Updated org role description" + ) +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients/get.py new file mode 100644 index 000000000..c7352c75d --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients/get.py @@ -0,0 +1,13 @@ +# List clients for a specific organization +org_id = 'SCALEKIT_ORGANIZATION_ID' + +# Retrieve all clients with default pagination +response = scalekit_client.m2m_client.list_organization_clients( + organization_id=org_id, + page_size=30 +) + +# Access the clients list +clients = response.clients +for client in clients: + print(f"Client ID: {scalekit_client.id}, Name: {scalekit_client.name}") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients/post.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients/post.py new file mode 100644 index 000000000..0c9340e17 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients/post.py @@ -0,0 +1,19 @@ +from scalekit.v1.clients.clients_pb2 import OrganizationClient + +m2m_client = OrganizationClient( + name="GitHub Actions Deployment Service", + description="Service account for GitHub Actions to deploy applications +to production", + custom_claims=[ + {"key": "github_repository", "value": "acmecorp/inventory-service"}, + {"key": "environment", "value": "production_us"} + ], + scopes=["deploy:applications", "read:deployments"], + audience=["deployment-api.acmecorp.com"], + expiry=3600 +) + +response = scalekit_client.m2m_client.create_organization_client( + organization_id="SCALEKIT_ORGANIZATION_ID", + m2m_client=m2m_client +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/delete.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/delete.py new file mode 100644 index 000000000..fc0c56789 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/delete.py @@ -0,0 +1,9 @@ +# Get client ID from environment variables +org_id = '' +client_id = os.environ['M2M_CLIENT_ID'] + +# Delete the specified client from the organization +response = scalekit_client.m2m_client.delete_organization_client( + organization_id=org_id, + client_id=client_id +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/get.py new file mode 100644 index 000000000..a4d98c22a --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/get.py @@ -0,0 +1,9 @@ +# Get client ID from environment variables +org_id = 'SCALEKIT_ORGANIZATION_ID' +client_id = os.environ['M2M_CLIENT_ID'] + +# Fetch client details for the specified organization +response = scalekit_client.m2m_client.get_organization_client( + organization_id=org_id, + client_id=client_id +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/patch.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/patch.py new file mode 100644 index 000000000..bdf59e892 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/patch.py @@ -0,0 +1,19 @@ +from scalekit.v1.clients.clients_pb2 import OrganizationClient + +org_id = '' +client_id = os.environ['M2M_CLIENT_ID'] + +update_m2m_client = OrganizationClient( + description="Service account for GitHub Actions to deploy applications +to production_eu", + custom_claims=[ + {"key": "github_repository", "value": "acmecorp/inventory"}, + {"key": "environment", "value": "production_eu"} + ] +) + +response = scalekit_client.m2m_client.update_organization_client( + organization_id=org_id, + client_id=client_id, + m2m_client=update_m2m_client +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}_secrets/post.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}_secrets/post.py new file mode 100644 index 000000000..6c6ad6b5e --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}_secrets/post.py @@ -0,0 +1,12 @@ +# Get client ID from environment variables +org_id = 'SCALEKIT_ORGANIZATION_ID' +client_id = os.environ['M2M_CLIENT_ID'] + +# Add a new secret to the specified client +response = scalekit_client.m2m_client.add_organization_client_secret( + organization_id=org_id, + client_id=client_id +) + +# Extract the secret ID from the response +secret_id = response[0].secret.id \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}_secrets_{secret_id}/delete.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}_secrets_{secret_id}/delete.py new file mode 100644 index 000000000..e71ff7b07 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}_secrets_{secret_id}/delete.py @@ -0,0 +1,11 @@ +# Get client and secret IDs from environment variables +org_id = '' +client_id = os.environ['M2M_CLIENT_ID'] +secret_id = os.environ['M2M_SECRET_ID'] + +# Remove the specified secret from the client +response = scalekit_client.m2m_client.remove_organization_client_secret( + organization_id=org_id, + client_id=client_id, + secret_id=secret_id +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}/delete.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}/delete.py new file mode 100644 index 000000000..1e1a010ff --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}/delete.py @@ -0,0 +1,4 @@ +scalekit_client.connection.delete_connection( + organization_id, + connection_id +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}/get.py new file mode 100644 index 000000000..92e430c60 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}/get.py @@ -0,0 +1,4 @@ +connection = scalekit_client.connection.get_connection( + organization_id, + connection_id, +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.py new file mode 100644 index 000000000..eb79d14b7 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.py @@ -0,0 +1,4 @@ +scalekit_client.connection.disable_connection( + organization_id, + connection_id +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.py new file mode 100644 index 000000000..3cded2a14 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.py @@ -0,0 +1,4 @@ +scalekit_client.connection.enable_connection( + organization_id, + connection_id, +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories/get.py new file mode 100644 index 000000000..474c2fa5d --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories/get.py @@ -0,0 +1,3 @@ +directories_list = scalekit_client.directory.list_directories( + organization_id='' +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.py new file mode 100644 index 000000000..132671a55 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.py @@ -0,0 +1,3 @@ +directory_groups = scalekit_client.directory.list_directory_groups( + directory_id='', organization_id='' +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.py new file mode 100644 index 000000000..2923ac017 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.py @@ -0,0 +1,3 @@ +directory_users = scalekit_client.directory.list_directory_users( + directory_id='', organization_id='' +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}/get.py new file mode 100644 index 000000000..3a483542e --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}/get.py @@ -0,0 +1,4 @@ +directory = scalekit_client.directory.get_directory( + directory_id='', organization_id='' +) +print(f'Directory details: {directory}') \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.py new file mode 100644 index 000000000..18b322697 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.py @@ -0,0 +1,3 @@ +directory_response = scalekit_client.directory.disable_directory( + directory_id='', organization_id='' +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.py new file mode 100644 index 000000000..712b47e1f --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.py @@ -0,0 +1,3 @@ +directory_response = scalekit_client.directory.enable_directory( + directory_id='', organization_id='' +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains/get.py new file mode 100644 index 000000000..edd0cfddc --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains/get.py @@ -0,0 +1,7 @@ +# List all domains in an organization +response = scalekit_client.domain.list_domains( + organization_id="org_123", + domain_type="ORGANIZATION_DOMAIN" + ) +# - organization_id: Owning organization +# - domain_type: domain type \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains/post.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains/post.py new file mode 100644 index 000000000..b873f4032 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains/post.py @@ -0,0 +1,5 @@ +# Add a new domain to an organization +response = scalekit_client.domain.create_domain(organization_id="org-123", + + domain_name="example.com", + domain_type="ORGANIZATION_DOMAIN") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains_{id}/delete.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains_{id}/delete.py new file mode 100644 index 000000000..35a247be1 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains_{id}/delete.py @@ -0,0 +1,6 @@ +# Remove a domain from an organization +# Caution: Deletion is permanent and may affect user access +response = scalekit_client.domain.delete_domain( + organization_id="org_123", + domain_id="dom_123" +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains_{id}/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains_{id}/get.py new file mode 100644 index 000000000..e16f55327 --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_domains_{id}/get.py @@ -0,0 +1,2 @@ +# Fetch details of a specific domain +response = scalekit_client.domain.get_domain(organization_id="org_123", domain_id="dom_123") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_users/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_users/get.py new file mode 100644 index 000000000..390eac78e --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_users/get.py @@ -0,0 +1 @@ +resp, _ = scalekit_client.users.list_users(organization_id="org_123", page_size=50) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_users/post.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_users/post.py new file mode 100644 index 000000000..0e33d31ac --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_users/post.py @@ -0,0 +1,24 @@ +# Create user with membership +user = CreateUser( + email="john.doe@example.com", + external_id="ext_john_123", # Optional + user_profile={ + "first_name": "John", + "last_name": "Doe", + "name": "John Doe", + "locale": "en-US", + "phone_number": "+14155552671" + }, + membership={ + "roles": [{"name": "member"}] + } +) + +# Create user and membership in organization +response = scalekit_client.users.create_user_and_membership( + organization_id="your_org_id", + user=user, + send_invitation_email=True # Set to False if you don't want to send +email ) + + user_id = response[0].user.id \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.py new file mode 100644 index 000000000..433968c3b --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.py @@ -0,0 +1,5 @@ +resp = scalekit_client.users.list_user_permissions( + organization_id="org_123", + user_id="usr_123", +) +permissions = resp.permissions \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.py b/openapi/code_samples/python/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.py new file mode 100644 index 000000000..c4bff419f --- /dev/null +++ b/openapi/code_samples/python/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.py @@ -0,0 +1,5 @@ +resp = scalekit_client.users.list_user_roles( + organization_id="org_123", + user_id="usr_123", +) +roles = resp.roles \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_passwordless_email_resend/post.py b/openapi/code_samples/python/api_v1_passwordless_email_resend/post.py new file mode 100644 index 000000000..381bd292a --- /dev/null +++ b/openapi/code_samples/python/api_v1_passwordless_email_resend/post.py @@ -0,0 +1,6 @@ +resend_response = scalekit_client.passwordless.resend_passwordless_email( + auth_request_id=auth_request_id, +) + +# New auth request ID from resend +new_auth_request_id = resend_response[0].auth_request_id \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_passwordless_email_send/post.py b/openapi/code_samples/python/api_v1_passwordless_email_send/post.py new file mode 100644 index 000000000..9a0f3f37b --- /dev/null +++ b/openapi/code_samples/python/api_v1_passwordless_email_send/post.py @@ -0,0 +1,14 @@ +response = scalekit_client.passwordless.send_passwordless_email( + email="john.doe@example.com", + template="SIGNIN", # or "SIGNUP", "UNSPECIFIED" + expires_in=100, + magiclink_auth_uri="https://www.google.com", + template_variables={ + "employeeID": "EMP523", + "teamName": "Alpha Team", + "supportEmail": "support@yourcompany.com", + }, +) + +# Extract auth request ID from response +auth_request_id = response[0].auth_request_id \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_passwordless_email_verify/post.py b/openapi/code_samples/python/api_v1_passwordless_email_verify/post.py new file mode 100644 index 000000000..68f441903 --- /dev/null +++ b/openapi/code_samples/python/api_v1_passwordless_email_verify/post.py @@ -0,0 +1,13 @@ +# Verify with OTP code +verify_response = scalekit_client.passwordless.verify_passwordless_email( + code="123456", # OTP code received via email + auth_request_id=auth_request_id, +) + +# Verify with magic link token +verify_response = scalekit_client.passwordless.verify_passwordless_email( + link_token=link_token, # Magic link token from URL +) + +# User verified successfully +user_email = verify_response[0].email \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_permissions/get.py b/openapi/code_samples/python/api_v1_permissions/get.py new file mode 100644 index 000000000..0239ef847 --- /dev/null +++ b/openapi/code_samples/python/api_v1_permissions/get.py @@ -0,0 +1 @@ +res = scalekit_client.permissions.list_permissions() \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_permissions/post.py b/openapi/code_samples/python/api_v1_permissions/post.py new file mode 100644 index 000000000..f2a97c739 --- /dev/null +++ b/openapi/code_samples/python/api_v1_permissions/post.py @@ -0,0 +1,8 @@ +from scalekit.v1.roles.roles_pb2 import CreatePermission + +permission = CreatePermission( + name="read:users", + description="Allows reading users" +) + +scalekit_client.permissions.create_permission(permission=permission) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_permissions_{permission_name}/delete.py b/openapi/code_samples/python/api_v1_permissions_{permission_name}/delete.py new file mode 100644 index 000000000..77060a854 --- /dev/null +++ b/openapi/code_samples/python/api_v1_permissions_{permission_name}/delete.py @@ -0,0 +1,3 @@ +scalekit_client.permissions.delete_permission( + permission_name="read:users" +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_permissions_{permission_name}/get.py b/openapi/code_samples/python/api_v1_permissions_{permission_name}/get.py new file mode 100644 index 000000000..12df2b2c9 --- /dev/null +++ b/openapi/code_samples/python/api_v1_permissions_{permission_name}/get.py @@ -0,0 +1,3 @@ +res = scalekit_client.permissions.get_permission( + permission_name="read:users" +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_permissions_{permission_name}/put.py b/openapi/code_samples/python/api_v1_permissions_{permission_name}/put.py new file mode 100644 index 000000000..7bdddb646 --- /dev/null +++ b/openapi/code_samples/python/api_v1_permissions_{permission_name}/put.py @@ -0,0 +1,9 @@ +from scalekit.v1.roles.roles_pb2 import CreatePermission + +scalekit_client.permissions.update_permission( + permission_name="read:users", + permission=CreatePermission( + name="read:users", + description="Allows reading user resources" + ) +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_roles/get.py b/openapi/code_samples/python/api_v1_roles/get.py new file mode 100644 index 000000000..a5d05ce53 --- /dev/null +++ b/openapi/code_samples/python/api_v1_roles/get.py @@ -0,0 +1 @@ +res = scalekit_client.roles.list_roles() \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_roles/post.py b/openapi/code_samples/python/api_v1_roles/post.py new file mode 100644 index 000000000..fb48fbe59 --- /dev/null +++ b/openapi/code_samples/python/api_v1_roles/post.py @@ -0,0 +1,11 @@ +from scalekit.v1.roles.roles_pb2 import CreateRole + +role = CreateRole( + name="admin", + display_name="Admin", + description="Environment-level role", + extends="base_role", # optional + permissions=["read:users"] # optional +) + +scalekit_client.roles.create_role(role=role) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_roles:set_defaults/patch.py b/openapi/code_samples/python/api_v1_roles:set_defaults/patch.py new file mode 100644 index 000000000..2cd6b8f54 --- /dev/null +++ b/openapi/code_samples/python/api_v1_roles:set_defaults/patch.py @@ -0,0 +1,7 @@ +from scalekit.v1.roles.roles_pb2 import UpdateDefaultRolesRequest + +res = scalekit_client.roles.update_default_roles( + default_roles=UpdateDefaultRolesRequest( + default_member_role="member" + ) +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_roles_{role_name}/delete.py b/openapi/code_samples/python/api_v1_roles_{role_name}/delete.py new file mode 100644 index 000000000..d6f024a42 --- /dev/null +++ b/openapi/code_samples/python/api_v1_roles_{role_name}/delete.py @@ -0,0 +1,8 @@ +# Basic delete +scalekit_client.roles.delete_role(role_name="admin") + +# With reassignment +scalekit_client.roles.delete_role( + role_name="admin", + reassign_role_name="member" +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_roles_{role_name}/get.py b/openapi/code_samples/python/api_v1_roles_{role_name}/get.py new file mode 100644 index 000000000..d44fa2bda --- /dev/null +++ b/openapi/code_samples/python/api_v1_roles_{role_name}/get.py @@ -0,0 +1 @@ +res = scalekit_client.roles.get_role(role_name="admin") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_roles_{role_name}/put.py b/openapi/code_samples/python/api_v1_roles_{role_name}/put.py new file mode 100644 index 000000000..9a957b3d9 --- /dev/null +++ b/openapi/code_samples/python/api_v1_roles_{role_name}/put.py @@ -0,0 +1,9 @@ +from scalekit.v1.roles.roles_pb2 import UpdateRole + +scalekit_client.roles.update_role( + role_name="admin", + role=UpdateRole( + display_name="Admin (Updated)", + description="Updated description" + ) +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_roles_{role_name}_dependents/get.py b/openapi/code_samples/python/api_v1_roles_{role_name}_dependents/get.py new file mode 100644 index 000000000..663272c01 --- /dev/null +++ b/openapi/code_samples/python/api_v1_roles_{role_name}_dependents/get.py @@ -0,0 +1 @@ +res = scalekit_client.roles.list_dependent_roles(role_name="admin") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_roles_{role_name}_permissions/get.py b/openapi/code_samples/python/api_v1_roles_{role_name}_permissions/get.py new file mode 100644 index 000000000..8e3bb1df0 --- /dev/null +++ b/openapi/code_samples/python/api_v1_roles_{role_name}_permissions/get.py @@ -0,0 +1 @@ +res = scalekit_client.permissions.list_role_permissions(role_name="admin") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_roles_{role_name}_permissions/post.py b/openapi/code_samples/python/api_v1_roles_{role_name}_permissions/post.py new file mode 100644 index 000000000..cd39902d9 --- /dev/null +++ b/openapi/code_samples/python/api_v1_roles_{role_name}_permissions/post.py @@ -0,0 +1,4 @@ +scalekit_client.permissions.add_permissions_to_role( + role_name="role_admin", + permission_names=["perm.read", "perm.write"] +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_roles_{role_name}_permissions_{permission_name}/delete.py b/openapi/code_samples/python/api_v1_roles_{role_name}_permissions_{permission_name}/delete.py new file mode 100644 index 000000000..0aaa3809e --- /dev/null +++ b/openapi/code_samples/python/api_v1_roles_{role_name}_permissions_{permission_name}/delete.py @@ -0,0 +1,4 @@ +scalekit_client.permissions.remove_permission_from_role( + role_name="admin", + permission_name="read:users" +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_roles_{role_name}_users:count/get.py b/openapi/code_samples/python/api_v1_roles_{role_name}_users:count/get.py new file mode 100644 index 000000000..47d69b7dc --- /dev/null +++ b/openapi/code_samples/python/api_v1_roles_{role_name}_users:count/get.py @@ -0,0 +1 @@ +res = scalekit_client.roles.get_role_users_count(role_name="admin") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_sessions_{session_id}/get.py b/openapi/code_samples/python/api_v1_sessions_{session_id}/get.py new file mode 100644 index 000000000..defe66a4f --- /dev/null +++ b/openapi/code_samples/python/api_v1_sessions_{session_id}/get.py @@ -0,0 +1 @@ +res = scalekit_client.sessions.get_session(session_id="ses_123456789") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_sessions_{session_id}_revoke/post.py b/openapi/code_samples/python/api_v1_sessions_{session_id}_revoke/post.py new file mode 100644 index 000000000..c6fcf67de --- /dev/null +++ b/openapi/code_samples/python/api_v1_sessions_{session_id}_revoke/post.py @@ -0,0 +1 @@ +res = scalekit_client.sessions.revoke_session(session_id="ses_123456789") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_users/get.py b/openapi/code_samples/python/api_v1_users/get.py new file mode 100644 index 000000000..4af01957e --- /dev/null +++ b/openapi/code_samples/python/api_v1_users/get.py @@ -0,0 +1,2 @@ +# pass empty org to fetch all users in environment +resp,_ = scalekit_client.users.list_users(organization_id="", page_size=100) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_users_{id}/delete.py b/openapi/code_samples/python/api_v1_users_{id}/delete.py new file mode 100644 index 000000000..5376746d5 --- /dev/null +++ b/openapi/code_samples/python/api_v1_users_{id}/delete.py @@ -0,0 +1,2 @@ +scalekit_client.users.delete_user(organization_id="org_123", + user_id="usr_123") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_users_{id}/get.py b/openapi/code_samples/python/api_v1_users_{id}/get.py new file mode 100644 index 000000000..71f77a0e2 --- /dev/null +++ b/openapi/code_samples/python/api_v1_users_{id}/get.py @@ -0,0 +1,2 @@ +resp = scalekit_client.users.get_user(user_id="usr_123456") +user = resp.user \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_users_{id}/patch.py b/openapi/code_samples/python/api_v1_users_{id}/patch.py new file mode 100644 index 000000000..17c4835b6 --- /dev/null +++ b/openapi/code_samples/python/api_v1_users_{id}/patch.py @@ -0,0 +1,18 @@ +import os +from scalekit import ScalekitClient +from scalekit.v1.users.users_pb2 import UpdateUser +from scalekit.v1.commons.commons_pb2 import UserProfile +scalekit_client = ScalekitClient( + env_url=os.getenv("SCALEKIT_ENV_URL"), + client_id=os.getenv("SCALEKIT_CLIENT_ID"), + client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), +) +update_user = UpdateUser( + user_profile=UserProfile( + first_name="John", + last_name="Smith" + ), + metadata={"department": "sales"} +) +scalekit_client.users.update_user(organization_id="org_123", + user=update_user) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_users_{user_id}_sessions/get.py b/openapi/code_samples/python/api_v1_users_{user_id}_sessions/get.py new file mode 100644 index 000000000..360b23eaa --- /dev/null +++ b/openapi/code_samples/python/api_v1_users_{user_id}_sessions/get.py @@ -0,0 +1,18 @@ +# Basic usage +res = scalekit_client.sessions.get_user_sessions(user_id="user_123") + +# With pagination and filtering +from google.protobuf.timestamp_pb2 import Timestamp +from datetime import datetime + +start_time = Timestamp() +start_time.FromDatetime(datetime(2024, 1, 1)) +end_time = Timestamp() +end_time.FromDatetime(datetime(2024, 12, 31)) + +filter_obj = scalekit_client.sessions.create_session_filter( + status=["ACTIVE"], start_time=start_time, end_time=end_time +) +res = scalekit_client.sessions.get_user_sessions( + user_id="user_123", page_size=10, page_token="next_page_token", filter=filter_obj +) \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_users_{user_id}_sessions_revoke/post.py b/openapi/code_samples/python/api_v1_users_{user_id}_sessions_revoke/post.py new file mode 100644 index 000000000..7028f0ebb --- /dev/null +++ b/openapi/code_samples/python/api_v1_users_{user_id}_sessions_revoke/post.py @@ -0,0 +1 @@ +res = scalekit_client.sessions.revoke_all_user_sessions(user_id="user_123") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_webauthn_credentials/get.py b/openapi/code_samples/python/api_v1_webauthn_credentials/get.py new file mode 100644 index 000000000..98e263f89 --- /dev/null +++ b/openapi/code_samples/python/api_v1_webauthn_credentials/get.py @@ -0,0 +1 @@ +res = scalekit_client.webauthn.list_credentials(user_id="user_123") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_webauthn_credentials_{credential_id}/delete.py b/openapi/code_samples/python/api_v1_webauthn_credentials_{credential_id}/delete.py new file mode 100644 index 000000000..891299b2f --- /dev/null +++ b/openapi/code_samples/python/api_v1_webauthn_credentials_{credential_id}/delete.py @@ -0,0 +1 @@ +res = scalekit_client.webauthn.delete_credential(credential_id="wac_123") \ No newline at end of file diff --git a/openapi/code_samples/python/api_v1_webauthn_credentials_{credential_id}/patch.py b/openapi/code_samples/python/api_v1_webauthn_credentials_{credential_id}/patch.py new file mode 100644 index 000000000..48c3e0602 --- /dev/null +++ b/openapi/code_samples/python/api_v1_webauthn_credentials_{credential_id}/patch.py @@ -0,0 +1,4 @@ +res = scalekit_client.webauthn.update_credential( + credential_id="wac_123", + display_name="Work Laptop Passkey" +) \ No newline at end of file diff --git a/openapi/components/schemas/HelpInfoLink.yaml b/openapi/components/schemas/HelpInfoLink.yaml new file mode 100644 index 000000000..ac17654f3 --- /dev/null +++ b/openapi/components/schemas/HelpInfoLink.yaml @@ -0,0 +1,11 @@ +description: A documentation or reference link. +type: object +properties: + description: + description: Human-readable label for the link (e.g. "User verification flow"). + type: string + url: + description: >- + Absolute URL to the documentation page (e.g. + "https://docs.scalekit.com/..."). + type: string diff --git a/openapi/components/schemas/OrganizationServiceUpdateOrganizationSessionPolicyBody.yaml b/openapi/components/schemas/OrganizationServiceUpdateOrganizationSessionPolicyBody.yaml new file mode 100644 index 000000000..1a01d0d65 --- /dev/null +++ b/openapi/components/schemas/OrganizationServiceUpdateOrganizationSessionPolicyBody.yaml @@ -0,0 +1,47 @@ +type: object +properties: + absolute_session_timeout: + description: >- + The absolute session timeout value. The unit is specified by + absolute_session_timeout_unit. Omit when policy_source is APPLICATION. + type: integer + format: int32 + examples: + - 360 + absolute_session_timeout_unit: + description: >- + Unit for absolute_session_timeout. Accepted values: 'MINUTES', 'HOURS', + 'DAYS'. Defaults to MINUTES. + $ref: ./commonsTimeUnit.yaml + examples: + - MINUTES + idle_session_timeout: + description: >- + The idle session timeout value. The unit is specified by + idle_session_timeout_unit. Omit when idle_session_timeout_enabled is + false. + type: integer + format: int32 + examples: + - 84 + idle_session_timeout_enabled: + description: >- + Whether idle session timeout is enabled. Omit when policy_source is + APPLICATION. + type: boolean + examples: + - true + idle_session_timeout_unit: + description: >- + Unit for idle_session_timeout. Accepted values: 'MINUTES', 'HOURS', + 'DAYS'. Defaults to MINUTES. + $ref: ./commonsTimeUnit.yaml + examples: + - MINUTES + policy_source: + description: >- + Policy source. Send 'APPLICATION' to revert to application defaults. Send + 'CUSTOM' with timeout values to activate a custom policy. + $ref: ./organizationsSessionPolicyType.yaml + examples: + - CUSTOM diff --git a/openapi/components/schemas/OrganizationServiceUpsertUserManagementSettingsBody.yaml b/openapi/components/schemas/OrganizationServiceUpsertUserManagementSettingsBody.yaml new file mode 100644 index 000000000..3d9ecc708 --- /dev/null +++ b/openapi/components/schemas/OrganizationServiceUpsertUserManagementSettingsBody.yaml @@ -0,0 +1,5 @@ +type: object +properties: + settings: + description: The new values for the setting fields to patch. + $ref: ./organizationsOrganizationUserManagementSettings.yaml diff --git a/openapi/components/schemas/RolesServiceAddPermissionsToRoleBody.yaml b/openapi/components/schemas/RolesServiceAddPermissionsToRoleBody.yaml new file mode 100644 index 000000000..66245ce74 --- /dev/null +++ b/openapi/components/schemas/RolesServiceAddPermissionsToRoleBody.yaml @@ -0,0 +1,7 @@ +type: object +properties: + permission_names: + description: List of permission names to add to the role + type: array + items: + type: string diff --git a/openapi/components/schemas/RolesServiceUpdateDefaultOrganizationRolesBody.yaml b/openapi/components/schemas/RolesServiceUpdateDefaultOrganizationRolesBody.yaml new file mode 100644 index 000000000..1f1133828 --- /dev/null +++ b/openapi/components/schemas/RolesServiceUpdateDefaultOrganizationRolesBody.yaml @@ -0,0 +1,7 @@ +type: object +properties: + default_member_role: + description: Unique name of the default member role + type: string + examples: + - member diff --git a/openapi/components/schemas/ScalekitEvent.yaml b/openapi/components/schemas/ScalekitEvent.yaml new file mode 100644 index 000000000..5a61c27cc --- /dev/null +++ b/openapi/components/schemas/ScalekitEvent.yaml @@ -0,0 +1,101 @@ +type: object +required: + - spec_version + - id + - type + - occurred_at + - environment_id + - object +properties: + spec_version: + type: string + example: '1' + description: The webhook specification version + pattern: ^[0-9]+$ + id: + type: string + pattern: ^evt_ + example: evt_1234567890abcdef + description: Unique identifier for the webhook event (must be prefixed with "evt_") + minLength: 1 + maxLength: 32 + type: + type: string + example: organization.created + description: The event type + enum: + - organization.created + - organization.updated + - organization.deleted + - organization.sso_created + - organization.sso_deleted + - organization.sso_enabled + - organization.sso_disabled + - user.signup + - user.login + - user.logout + - user.organization_invitation + - user.organization_membership_created + - user.organization_membership_updated + - user.organization_membership_deleted + - organization.directory.user_created + - organization.directory.user_updated + - organization.directory.user_deleted + - organization.directory.group_created + - organization.directory.group_updated + - organization.directory.group_deleted + - organization.directory_enabled + - organization.directory_disabled + - role.created + - role.updated + - role.deleted + - permission.created + - permission.updated + - permission.deleted + occurred_at: + type: string + format: date-time + description: When the event occurred (ISO 8601 format) + example: '2024-01-01T00:00:00Z' + environment_id: + type: string + pattern: ^env_ + example: env_1234567890abcdef + description: The environment ID where the event occurred + minLength: 1 + maxLength: 32 + organization_id: + type: string + pattern: ^org_ + example: org_1234567890abcdef + description: The organization ID (if applicable) + minLength: 1 + maxLength: 32 + object: + type: string + description: The type of object that triggered the webhook + enum: + - Organization + - Connection + - Role + - Directory + - DirectoryUser + - DirectoryGroup + - Permission + - OrgMembership + - User + example: Organization + data: + type: object + description: The event payload (structure varies by event type) + additionalProperties: true + example: + id: org_1234567890abcdef + name: Example Organization + created_at: '2024-01-01T00:00:00Z' + display_name: + type: string + description: Human-readable display name for the event + example: Organization Created + minLength: 1 + maxLength: 200 diff --git a/openapi/components/schemas/TestUser.yaml b/openapi/components/schemas/TestUser.yaml new file mode 100644 index 000000000..e28b3498c --- /dev/null +++ b/openapi/components/schemas/TestUser.yaml @@ -0,0 +1,27 @@ +type: object +properties: + enabled: + type: boolean + description: Whether test user mode is enabled for this environment. + example: true + emails: + type: array + items: + type: string + format: email + description: >- + Explicit list of test user email addresses. Each email must contain + '+sktest' in the local part (e.g. alice+sktest@example.com). Maximum 5 + emails per environment (configurable server-side). + example: + - alice+sktest@example.com + - bob+sktest@example.com + static_confirmation_code: + type: string + pattern: ^[0-9]{6}$ + minLength: 6 + maxLength: 6 + description: >- + Six-digit static OTP code used in place of a real verification email for + matched test users. + example: '424242' diff --git a/openapi/components/schemas/UserServiceResendInviteBody.yaml b/openapi/components/schemas/UserServiceResendInviteBody.yaml new file mode 100644 index 000000000..91bf3091f --- /dev/null +++ b/openapi/components/schemas/UserServiceResendInviteBody.yaml @@ -0,0 +1 @@ +type: object diff --git a/openapi/components/schemas/ValidationErrorInfoFieldViolation.yaml b/openapi/components/schemas/ValidationErrorInfoFieldViolation.yaml new file mode 100644 index 000000000..ee49b6cf2 --- /dev/null +++ b/openapi/components/schemas/ValidationErrorInfoFieldViolation.yaml @@ -0,0 +1,10 @@ +description: A message type used to describe a single bad request field. +type: object +properties: + constraint: + type: string + description: + description: A description of why the request element is bad. + type: string + field: + type: string diff --git a/openapi/components/schemas/WebAuthConfigurationAttestation.yaml b/openapi/components/schemas/WebAuthConfigurationAttestation.yaml new file mode 100644 index 000000000..aa87ef8ff --- /dev/null +++ b/openapi/components/schemas/WebAuthConfigurationAttestation.yaml @@ -0,0 +1,13 @@ +type: object +title: Attestation preferences for registration +properties: + conveyance_preference: + type: string + title: Conveyance preference + enterprise_approved_ids: + type: array + title: >- + Enterprise-approved IDs (optional allowlist when enterprise attestation is + used) + items: + type: string diff --git a/openapi/components/schemas/WebAuthConfigurationAuthenticatorSelection.yaml b/openapi/components/schemas/WebAuthConfigurationAuthenticatorSelection.yaml new file mode 100644 index 000000000..20f5f947d --- /dev/null +++ b/openapi/components/schemas/WebAuthConfigurationAuthenticatorSelection.yaml @@ -0,0 +1,7 @@ +type: object +properties: + authenticator_attachment: + type: string + user_verification: + type: string + title: User verification requirement diff --git a/openapi/components/schemas/WebAuthConfigurationAuthenticators.yaml b/openapi/components/schemas/WebAuthConfigurationAuthenticators.yaml new file mode 100644 index 000000000..5e0173da8 --- /dev/null +++ b/openapi/components/schemas/WebAuthConfigurationAuthenticators.yaml @@ -0,0 +1,50 @@ +type: object +properties: + desired_authenticator_status: + description: >- + provides the list of statuses which are considered undesirable for status + report validation purposes. Should be used with validate_status set to + true. + type: array + items: + type: string + default: '[]' + undesired_authenticator_status: + description: >- + provides the list of statuses which are considered undesirable for status + report validation purposes. Should be used with validate_status set to + true. + type: array + items: + type: string + default: >- + ['ATTESTATION_KEY_COMPROMISE', 'USER_VERIFICATION_BYPASS', + 'USER_KEY_REMOTE_COMPROMISE', 'USER_KEY_PHYSICAL_COMPROMISE', 'REVOKED'] + validate_anchors: + description: >- + when set to true enables the validation of the attestation statement + against the trust anchor from the metadata statement. + type: boolean + validate_attestation_type: + description: >- + when set to true enables the validation of the attestation statements type + against the known types the authenticator can produce. + type: boolean + validate_entry: + description: >- + requires that the provided metadata has an entry for the given + authenticator to be considered valid. By default an AAGUID which has a + zero value should fail validation if validate_entry_permit_zero_aaguid is + not provided with the value of true. + type: boolean + validate_entry_permit_zero_aaguid: + description: >- + is an option that permits a zero'd AAGUID from an attestation statement to + automatically pass metadata validations. Generally helpful to use with + validate_entry. + type: boolean + validate_status: + description: >- + when set to true enables the validation of the attestation statements + AAGUID against the desired and undesired lists + type: boolean diff --git a/openapi/components/schemas/WebAuthConfigurationRp.yaml b/openapi/components/schemas/WebAuthConfigurationRp.yaml new file mode 100644 index 000000000..963500b81 --- /dev/null +++ b/openapi/components/schemas/WebAuthConfigurationRp.yaml @@ -0,0 +1,19 @@ +type: object +title: Rp contains relying party identifiers and origins +properties: + ids: + type: array + title: >- + Relying party IDs (derived from environment domain and verified custom + domain) + + At least one required; must be hostnames without scheme or path + items: + type: string + origins: + type: array + title: |- + Allowed origins corresponding to the RP IDs (https://) + At least one required; must be HTTPS origins + items: + type: string diff --git a/openapi/components/schemas/WebAuthConfigurationTimeout.yaml b/openapi/components/schemas/WebAuthConfigurationTimeout.yaml new file mode 100644 index 000000000..317950b6a --- /dev/null +++ b/openapi/components/schemas/WebAuthConfigurationTimeout.yaml @@ -0,0 +1,18 @@ +type: object +properties: + login: + description: Login timeout duration + type: string + default: '"300s"' + login_uvd: + description: Login timeout duration when user verification is discouraged + type: string + default: '"300s"' + registration: + description: Registration timeout duration + type: string + default: '"300s"' + registration_uvd: + description: Registration timeout duration when user verification is discouraged + type: string + default: '"300s"' diff --git a/openapi/components/schemas/WebAuthnCredentialAuthenticator.yaml b/openapi/components/schemas/WebAuthnCredentialAuthenticator.yaml new file mode 100644 index 000000000..802493091 --- /dev/null +++ b/openapi/components/schemas/WebAuthnCredentialAuthenticator.yaml @@ -0,0 +1,21 @@ +type: object +properties: + aaguid: + description: Authenticator Attestation GUID (AAGUID) identifying the device model + type: string + attachment: + description: 'Attachment type: "platform" (built-in) or "cross-platform"' + type: string + examples: + - platform + icon_dark: + description: Icon URL for dark theme display + type: string + icon_light: + description: Icon URL for light theme display + type: string + name: + description: Human-readable name of the authenticator model + type: string + examples: + - Apple Touch ID diff --git a/openapi/components/schemas/WebAuthnCredentialAuthenticatorFlags.yaml b/openapi/components/schemas/WebAuthnCredentialAuthenticatorFlags.yaml new file mode 100644 index 000000000..8504e0e85 --- /dev/null +++ b/openapi/components/schemas/WebAuthnCredentialAuthenticatorFlags.yaml @@ -0,0 +1,14 @@ +type: object +properties: + backup_eligible: + description: Whether this credential can be backed up to another device + type: boolean + backup_state: + description: Whether this credential was synced or backed up + type: boolean + user_present: + description: Whether the user was present during authentication + type: boolean + user_verified: + description: Whether the user was verified (e.g., fingerprint, PIN) + type: boolean diff --git a/openapi/components/schemas/WebAuthnCredentialClientInfo.yaml b/openapi/components/schemas/WebAuthnCredentialClientInfo.yaml new file mode 100644 index 000000000..6a3cff16f --- /dev/null +++ b/openapi/components/schemas/WebAuthnCredentialClientInfo.yaml @@ -0,0 +1,22 @@ +type: object +properties: + city: + description: City name + type: string + examples: + - San Francisco + ip: + description: IP address from which credential was registered + type: string + examples: + - 192.0.2.1 + region: + description: Geographic region (e.g., "US") + type: string + examples: + - US + region_subdivision: + description: Regional subdivision (e.g., "CA") + type: string + examples: + - CA diff --git a/openapi/components/schemas/WebAuthnCredentialUserAgent.yaml b/openapi/components/schemas/WebAuthnCredentialUserAgent.yaml new file mode 100644 index 000000000..ca5827224 --- /dev/null +++ b/openapi/components/schemas/WebAuthnCredentialUserAgent.yaml @@ -0,0 +1,38 @@ +type: object +properties: + browser: + description: Browser name (e.g., "Chrome", "Safari") + type: string + examples: + - Chrome + browser_version: + description: Browser version number + type: string + examples: + - 120.0.6099.129 + device_model: + description: Device model if available + type: string + examples: + - iPhone15,2 + device_type: + description: 'Device type: "desktop", "mobile", or "tablet"' + type: string + examples: + - mobile + os: + description: Operating system name (e.g., "Windows", "iOS") + type: string + examples: + - macOS + os_version: + description: Operating system version + type: string + examples: + - '14.2' + raw: + description: Raw user agent string from the browser + type: string + url: + description: Parsed user agent URL reference + type: string diff --git a/openapi/components/schemas/WebAuthnServiceUpdateCredentialBody.yaml b/openapi/components/schemas/WebAuthnServiceUpdateCredentialBody.yaml new file mode 100644 index 000000000..030fe286c --- /dev/null +++ b/openapi/components/schemas/WebAuthnServiceUpdateCredentialBody.yaml @@ -0,0 +1,7 @@ +type: object +properties: + display_name: + description: Human-friendly name for this credential (1-120 characters) + type: string + examples: + - My iPhone 15 Pro diff --git a/openapi/components/schemas/authpasswordlessPasswordlessType.yaml b/openapi/components/schemas/authpasswordlessPasswordlessType.yaml new file mode 100644 index 000000000..b34ad286a --- /dev/null +++ b/openapi/components/schemas/authpasswordlessPasswordlessType.yaml @@ -0,0 +1,5 @@ +type: string +enum: + - OTP + - LINK + - LINK_OTP diff --git a/openapi/components/schemas/clientsClientSecret.yaml b/openapi/components/schemas/clientsClientSecret.yaml new file mode 100644 index 000000000..17cfe1fb3 --- /dev/null +++ b/openapi/components/schemas/clientsClientSecret.yaml @@ -0,0 +1,80 @@ +description: >- + A secure credential used for authenticating an API client. Each client can + have multiple secrets for key rotation purposes. +type: object +title: Client Secret +properties: + create_time: + description: >- + The timestamp when this secret was created. This field is automatically + set by the server and cannot be modified. + type: string + format: date-time + examples: + - '2024-01-05T14:48:00Z' + created_by: + description: >- + The identifier of the user or system that created this secret. This field + helps track who created the secret for audit and compliance purposes. + type: string + examples: + - user_12345 + expire_time: + description: >- + The timestamp when this secret will expire. After this time, the secret + cannot be used for authentication regardless of its status. If not set, + the secret does not expire. + type: string + format: date-time + examples: + - '2025-01-05T14:48:00Z' + id: + description: >- + The unique identifier for this client secret. This ID is used to reference + the secret in API requests for management operations like updating or + deleting the secret. + type: string + examples: + - sec_1234abcd5678efgh + last_used_time: + description: >- + The timestamp when this secret was last used for authentication. This + field helps track secret usage for security monitoring and identifying + unused secrets that may be candidates for rotation. + type: string + format: date-time + examples: + - '2024-02-15T10:30:00Z' + plain_secret: + description: >- + The full plaintext secret value. This field is only populated when the + secret is first created and is never stored by the server. It must be + securely stored by the client application as it cannot be retrieved again. + type: string + examples: + - sec_1234567890abcdefghijklmnopqrstuvwxyz + secret_suffix: + description: >- + A suffix that helps identify this secret. This is the last few characters + of the full secret value but is not sufficient for authentication. Helps + identify which secret is being used in logs and debugging. + type: string + examples: + - xyzw + status: + description: >- + The current status of this secret. A secret must be ACTIVE to be used for + authentication. INACTIVE secrets cannot be used for authentication but are + retained for audit purposes. + $ref: ./clientsClientSecretStatus.yaml + examples: + - INACTIVE + update_time: + description: >- + The timestamp when this secret was last updated. This field is + automatically updated by the server when the secret's status changes or + other properties are modified. + type: string + format: date-time + examples: + - '2024-01-10T09:12:00Z' diff --git a/openapi/components/schemas/clientsClientSecretStatus.yaml b/openapi/components/schemas/clientsClientSecretStatus.yaml new file mode 100644 index 000000000..0a215fb6d --- /dev/null +++ b/openapi/components/schemas/clientsClientSecretStatus.yaml @@ -0,0 +1,10 @@ +description: >- + ClientSecretStatus indicates whether a client secret can be used for + authentication. + + ACTIVE secrets can be used for authentication while INACTIVE secrets cannot. + + - INACTIVE: The secret is inactive and cannot be used for authentication +type: string +enum: + - INACTIVE diff --git a/openapi/components/schemas/clientsCreateOrganizationClientResponse.yaml b/openapi/components/schemas/clientsCreateOrganizationClientResponse.yaml new file mode 100644 index 000000000..aa62ee347 --- /dev/null +++ b/openapi/components/schemas/clientsCreateOrganizationClientResponse.yaml @@ -0,0 +1,10 @@ +type: object +properties: + client: + description: Details of the created client + $ref: ./clientsM2MClient.yaml + plain_secret: + description: Client secret value (only returned once at creation) + type: string + examples: + - CdExsdErfccxDDssddfffgfeFHH1 diff --git a/openapi/components/schemas/clientsCreateOrganizationClientSecretResponse.yaml b/openapi/components/schemas/clientsCreateOrganizationClientSecretResponse.yaml new file mode 100644 index 000000000..2f8d8cf7c --- /dev/null +++ b/openapi/components/schemas/clientsCreateOrganizationClientSecretResponse.yaml @@ -0,0 +1,10 @@ +type: object +properties: + plain_secret: + description: Client secret value (only returned once at creation) + type: string + examples: + - m2morg_client_secret_xyz123 + secret: + description: Details of the created client secret + $ref: ./clientsClientSecret.yaml diff --git a/openapi/components/schemas/clientsCustomClaim.yaml b/openapi/components/schemas/clientsCustomClaim.yaml new file mode 100644 index 000000000..4fbadcea5 --- /dev/null +++ b/openapi/components/schemas/clientsCustomClaim.yaml @@ -0,0 +1,16 @@ +type: object +properties: + key: + description: >- + The name of the custom claim. Must be between 1 and 128 characters. Use + descriptive names that clearly indicate the claim's purpose. + type: string + examples: + - environment + value: + description: >- + The value of the custom claim. This value will be included in access + tokens issued to the client. + type: string + examples: + - production diff --git a/openapi/components/schemas/clientsGetOrganizationClientResponse.yaml b/openapi/components/schemas/clientsGetOrganizationClientResponse.yaml new file mode 100644 index 000000000..d7696c516 --- /dev/null +++ b/openapi/components/schemas/clientsGetOrganizationClientResponse.yaml @@ -0,0 +1,5 @@ +type: object +properties: + client: + description: Details of the requested client + $ref: ./clientsM2MClient.yaml diff --git a/openapi/components/schemas/clientsListOrganizationClientsResponse.yaml b/openapi/components/schemas/clientsListOrganizationClientsResponse.yaml new file mode 100644 index 000000000..0f314ece1 --- /dev/null +++ b/openapi/components/schemas/clientsListOrganizationClientsResponse.yaml @@ -0,0 +1,39 @@ +description: >- + Response message containing a paginated list of API clients for the specified + organization. +type: object +title: List Organization Clients Response +properties: + clients: + description: >- + List of API client objects for the organization. Each client includes its + configuration, metadata, and active secrets (without exposing actual + secret values). + type: array + title: List of organization API clients + items: + type: object + $ref: ./clientsM2MClient.yaml + next_page_token: + description: >- + Pagination token for the next page of results. Use this token to fetch the + next page. + type: string + title: Pagination token for the next page of results + examples: + - + prev_page_token: + description: >- + Pagination token for the previous page of results. Use this token to fetch + the previous page. + type: string + title: Pagination token for the previous page of results + examples: + - + total_size: + description: Total number of API clients in the organization. + type: integer + format: int64 + title: Total number of clients in the organization + examples: + - 30 diff --git a/openapi/components/schemas/clientsM2MClient.yaml b/openapi/components/schemas/clientsM2MClient.yaml new file mode 100644 index 000000000..3d8019c6e --- /dev/null +++ b/openapi/components/schemas/clientsM2MClient.yaml @@ -0,0 +1,132 @@ +type: object +properties: + audience: + description: >- + The intended recipients of access tokens issued to this client. Each + audience value should be a URI that identifies an API or service. + type: array + items: + type: string + examples: + - - https://api.example.com + client_id: + description: >- + The unique identifier for this API client. This ID is used to identify the + client in API requests and logs. It is automatically generated when the + client is created and cannot be modified. + type: string + examples: + - m2morg_1231234233424344 + create_time: + description: >- + The timestamp when this API client was created. This field is + automatically set by the server and cannot be modified. + type: string + format: date-time + examples: + - '2024-01-05T14:48:00Z' + custom_claims: + description: >- + Additional claims included in access tokens issued to this client. These + claims provide context about the client and can be used for authorization + decisions. + type: array + items: + type: object + $ref: ./clientsCustomClaim.yaml + description: + description: >- + A detailed description of the client's purpose and usage. This helps + administrators understand what the client is used for. + type: string + examples: + - Service account for automated deployment processes + expiry: + description: Expiry time in seconds for the token generated by the client + type: string + format: int64 + examples: + - 3600 + is_cimd: + description: >- + Indicates if the client was created via Client ID Metadata Document + (CIMD). CIMD clients can update their own configuration according to the + CIMD specification. + type: boolean + examples: + - false + is_dcr: + description: >- + Indicates if the client was created via Dynamic Client Registration (DCR). + Clients created through DCR may have different management and lifecycle + policies compared to those created manually. + type: boolean + examples: + - false + metadata_uri: + description: >- + The URI to the client's metadata, which is utilized to obtain the client's + configuration details + type: string + examples: + - https://example.com/client-metadata.json + name: + description: >- + The display name of the API client. This name helps identify the client in + the dashboard and logs. + type: string + examples: + - GitHub Actions Deployment Service + organization_id: + description: >- + The ID of the organization that owns this API client. This ID is used to + associate the client with the correct organization and enforce + organization-specific access controls. + type: string + examples: + - org_1231234233424344 + redirect_uris: + description: >- + The redirect URI for this API client. This URI is used in the OAuth 2.0 + authorization flow to redirect users after authentication. + type: array + items: + type: string + examples: + - - https://example.com/callback + resource_id: + description: >- + The ID of the resource associated with this M2M client. This field is used + to link the client to a specific resource in the system. + type: string + examples: + - app_1231234233424344 + scopes: + description: >- + The OAuth 2.0 scopes granted to this client. These scopes determine what + resources and actions the client can access. + type: array + items: + type: string + examples: + - - deploy:resources + - read:deployments + secrets: + description: >- + List of client secrets associated with this client. Each secret can be + used for authentication, but only the most recently created secret is + typically active. Secrets are stored securely and their values are never + returned after creation. + type: array + items: + type: object + $ref: ./clientsClientSecret.yaml + update_time: + description: >- + The timestamp when this API client was last updated. This field is + automatically updated by the server whenever the client's configuration + changes. + type: string + format: date-time + examples: + - '2024-01-05T14:48:00Z' diff --git a/openapi/components/schemas/clientsOrganizationClient.yaml b/openapi/components/schemas/clientsOrganizationClient.yaml new file mode 100644 index 000000000..924cb27cd --- /dev/null +++ b/openapi/components/schemas/clientsOrganizationClient.yaml @@ -0,0 +1,60 @@ +type: object +properties: + audience: + description: >- + The intended recipients of the access tokens issued to this client. Each + audience value should be a URI that identifies the API or service that + will validate the token. + type: array + items: + type: string + examples: + - - https://api.example.com/api/analytics + - https://deployment-api.acmecorp.com + custom_claims: + description: >- + Additional claims to be included in access tokens issued to this client. + These claims provide context about the client and can be used for + authorization decisions. Keep claims minimal to avoid increasing token + size. + type: array + items: + type: object + $ref: ./clientsCustomClaim.yaml + examples: + - - key: environment + value: production + - key: service + value: deployment + description: + description: >- + A detailed explanation of the client's purpose and usage. This helps + administrators understand what the client is used for and who manages it. + type: string + examples: + - Service account for GitHub Actions to deploy resources to production + expiry: + description: Expiry time in seconds for the token generated by the client + type: string + format: int64 + examples: + - 3600 + name: + description: >- + A descriptive name for the API client that helps identify its purpose. + This name is displayed in the dashboard and logs. Must be between 1 and + 128 characters. + type: string + examples: + - GitHub Actions Deployment Service + scopes: + description: >- + OAuth 2.0 scopes that define the permissions granted to this client. Each + scope represents a specific permission or set of permissions. The client + can only access resources that match its granted scopes. + type: array + items: + type: string + examples: + - - deploy:resources + - read:deployments diff --git a/openapi/components/schemas/clientsUpdateOrganizationClientResponse.yaml b/openapi/components/schemas/clientsUpdateOrganizationClientResponse.yaml new file mode 100644 index 000000000..1fd764525 --- /dev/null +++ b/openapi/components/schemas/clientsUpdateOrganizationClientResponse.yaml @@ -0,0 +1,5 @@ +type: object +properties: + client: + description: Updated details of the client + $ref: ./clientsM2MClient.yaml diff --git a/openapi/components/schemas/commonsExternalIdentity.yaml b/openapi/components/schemas/commonsExternalIdentity.yaml new file mode 100644 index 000000000..92be9028f --- /dev/null +++ b/openapi/components/schemas/commonsExternalIdentity.yaml @@ -0,0 +1,59 @@ +type: object +properties: + connection_id: + description: >- + Unique identifier for the external identity connection. Immutable and + read-only. + type: string + readOnly: true + examples: + - conn_1234abcd5678efgh + connection_provider: + description: Type of the identity provider. + $ref: ./commonsIdentityProviderType.yaml + readOnly: true + examples: + - GOOGLE + connection_type: + description: Name of the external identity connection. + type: string + readOnly: true + examples: + - OAUTH + connection_user_id: + description: >- + Unique identifier for the user in the external identity provider system. + Immutable and read-only. + type: string + readOnly: true + examples: + - ext_user_12345 + created_time: + description: >- + Timestamp when this external identity connection was first created. + Immutable and read-only. + type: string + format: date-time + readOnly: true + is_social: + description: >- + Indicates if the identity provider is a social provider (true) or + enterprise/custom provider (false). Read-only. + type: boolean + readOnly: true + examples: + - true + last_login_time: + description: >- + Timestamp of the user's last successful login via this external identity + provider. Automatically updated by the system. + type: string + format: date-time + readOnly: true + last_synced_time: + description: >- + Timestamp of the last data synchronization for this external identity from + the provider. Automatically updated by the system. + type: string + format: date-time + readOnly: true diff --git a/openapi/components/schemas/commonsIdentityProviderType.yaml b/openapi/components/schemas/commonsIdentityProviderType.yaml new file mode 100644 index 000000000..5f6b76ebc --- /dev/null +++ b/openapi/components/schemas/commonsIdentityProviderType.yaml @@ -0,0 +1,18 @@ +type: string +enum: + - OKTA + - GOOGLE + - MICROSOFT_AD + - AUTH0 + - ONELOGIN + - PING_IDENTITY + - JUMPCLOUD + - CUSTOM + - GITHUB + - GITLAB + - LINKEDIN + - SALESFORCE + - MICROSOFT + - IDP_SIMULATOR + - SCALEKIT + - ADFS diff --git a/openapi/components/schemas/commonsMembershipStatus.yaml b/openapi/components/schemas/commonsMembershipStatus.yaml new file mode 100644 index 000000000..905ac743e --- /dev/null +++ b/openapi/components/schemas/commonsMembershipStatus.yaml @@ -0,0 +1,6 @@ +type: string +enum: + - ACTIVE + - INACTIVE + - PENDING_INVITE + - INVITE_EXPIRED diff --git a/openapi/components/schemas/commonsOrganizationMembership.yaml b/openapi/components/schemas/commonsOrganizationMembership.yaml new file mode 100644 index 000000000..cb9a2074d --- /dev/null +++ b/openapi/components/schemas/commonsOrganizationMembership.yaml @@ -0,0 +1,82 @@ +type: object +properties: + accepted_at: + description: Timestamp when the user accepted the invitation. + type: string + format: date-time + created_at: + description: Timestamp when the invitation was created. + type: string + format: date-time + display_name: + description: >- + Organization display name. This field stores a user-friendly name for the + organization that may be different from the formal name, often used for UI + display purposes. + type: string + examples: + - Acme Corporation + expires_at: + description: Timestamp when the invitation expired. + type: string + format: date-time + inviter_email: + description: ID of the user who invited this user. + type: string + join_time: + description: >- + Timestamp when the membership was created. Automatically set by the + server. + type: string + format: date-time + membership_status: + $ref: ./commonsMembershipStatus.yaml + metadata: + description: >- + Custom key-value pairs for storing additional user context. Keys (3-25 + chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + name: + description: >- + Organization name. This field stores the formal organization name used for + identification and display purposes. + type: string + examples: + - AcmeCorp + organization_id: + description: Unique identifier for the organization. Immutable and read-only. + type: string + examples: + - org_1234abcd5678efgh + permissions: + description: >- + Effective permissions granted to the user within the organization + (including inherited permissions from assigned roles). Lists the specific + actions and access rights the user can perform. + type: array + items: + type: string + examples: + - - read_projects + - write_tasks + - manage_users + provisioning_method: + description: |- + How the user was provisioned. + Possible values: + - `jit_using_sso` (Just-in-time provisioning during SSO login) + - `allowed_email_domain` (User joined via allowed email domain matching) + - `org_creator` (User created the organization) + - `direct_provision` (User was directly provisioned via API or SCIM) + - `invitation` (User was invited and accepted an invitation) + type: string + roles: + type: array + items: + type: object + $ref: ./commonsRole.yaml diff --git a/openapi/components/schemas/commonsRegionCode.yaml b/openapi/components/schemas/commonsRegionCode.yaml new file mode 100644 index 000000000..a3fe41f0e --- /dev/null +++ b/openapi/components/schemas/commonsRegionCode.yaml @@ -0,0 +1,4 @@ +type: string +enum: + - US + - EU diff --git a/openapi/components/schemas/commonsRole.yaml b/openapi/components/schemas/commonsRole.yaml new file mode 100644 index 000000000..a9188895c --- /dev/null +++ b/openapi/components/schemas/commonsRole.yaml @@ -0,0 +1,21 @@ +type: object +properties: + display_name: + description: Human-readable name for the role + type: string + examples: + - Dev Team + id: + description: Role ID + type: string + readOnly: true + examples: + - role_79643236410327240 + name: + description: >- + Attribute name/identifier for the role used in system operations and API + calls. This should be a machine-readable identifier that follows naming + conventions. + type: string + examples: + - team_dev diff --git a/openapi/components/schemas/commonsTimeUnit.yaml b/openapi/components/schemas/commonsTimeUnit.yaml new file mode 100644 index 000000000..9ee2a6587 --- /dev/null +++ b/openapi/components/schemas/commonsTimeUnit.yaml @@ -0,0 +1,5 @@ +type: string +enum: + - MINUTES + - HOURS + - DAYS diff --git a/openapi/components/schemas/commonsUserProfile.yaml b/openapi/components/schemas/commonsUserProfile.yaml new file mode 100644 index 000000000..09674b31f --- /dev/null +++ b/openapi/components/schemas/commonsUserProfile.yaml @@ -0,0 +1,163 @@ +type: object +properties: + custom_attributes: + description: >- + Custom attributes for extended user profile data and application-specific + information. This field stores business-specific user data like + department, job title, security clearances, project assignments, or any + other organizational attributes your application requires. Unlike system + metadata, these attributes are typically managed by administrators or + applications and are visible to end users for personalization and business + logic. Keys must be 3-25 characters, values must be 1-256 characters, with + a maximum of 20 key-value pairs. + type: object + additionalProperties: + type: string + examples: + - department: engineering + security_clearance: level2 + email_verified: + description: >- + Indicates if the user's email address has been verified. Automatically + updated by the system. + type: boolean + readOnly: true + examples: + - true + external_identities: + description: List of external identity connections associated with the user profile. + type: array + items: + type: object + $ref: ./commonsExternalIdentity.yaml + readOnly: true + family_name: + description: >- + The user's family name (last name or surname). This field stores the + user's last name and is combined with the given name to create the full + display name. The family name is used in formal communications, user + listings, and organizational directories throughout the system. Maximum + 255 characters allowed. + type: string + examples: + - Doe + gender: + description: >- + The user's gender identity information. This field stores the user's + gender identity for personalization, compliance reporting, or + organizational analytics purposes. This field supports any string value to + accommodate diverse gender identities and should be handled with + appropriate privacy considerations according to your organization's + policies and applicable regulations. + type: string + examples: + - male + given_name: + description: >- + The user's given name (first name). This field stores the user's first + name and is used for personalization, display purposes, and when + generating the full display name. The given name appears in user + interfaces, formal communications, and user listings throughout the + system. Maximum 255 characters allowed. + type: string + examples: + - John + groups: + description: >- + The list of group names the user belongs to within the organization. This + field stores the user's group memberships for role-based access control, + team assignments, and organizational structure. Groups are typically used + for permission management, collaborative access, and organizational + hierarchy. Each group name represents a distinct organizational unit or + team that the user is associated with. + type: array + items: + type: string + examples: + - - admin + - developer + id: + description: >- + Unique system-generated identifier for the user profile. Immutable and + read-only. + type: string + readOnly: true + examples: + - usr_profile_1234abcd5678efgh + locale: + description: >- + The user's preferred language and region settings using BCP-47 format + codes. This field customizes the user's experience with localized content, + date formats, number formatting, and UI language throughout the system. + When not specified, the user inherits the organization's default locale + settings. Common values include `en-US`, `en-GB`, `fr-FR`, `de-DE`, and + `es-ES`. + type: string + examples: + - en-US + metadata: + description: >- + Raw attributes received from identity providers during authentication. + This field stores the original user profile data as received from external + IdP systems (SAML, OIDC, etc.) including provider-specific claims and + attributes. These fields preserve the complete set of attributes received + from the identity source and are used for mapping, synchronization, and + audit purposes. Keys must be 3-25 characters, values must be 1-256 + characters, with a maximum of 20 key-value pairs. + type: object + additionalProperties: + type: string + examples: + - department: engineering + employee_type: full-time + idp_user_id: '12345' + name: + description: >- + The user's complete display name in formatted form. This field stores the + full name as a single string and is typically used when you want to set + the complete name rather than using separate given and family names. This + name appears in user interfaces, reports, directory listings, and anywhere + a formatted display name is needed. This field serves as a formatted + display name that complements the individual given_name and family_name + fields. + type: string + examples: + - John Michael Doe + phone_number: + description: >- + The user's phone number in E.164 international format. This field stores + the phone number for user contact and identification purposes. The phone + number must include the country code and be formatted according to E.164 + standards (e.g., `+1` for US numbers). This field is optional. + type: string + examples: + - '+14155552671' + phone_number_verified: + description: >- + Indicates if the user's phone number has been verified. Automatically + updated by the system. + type: boolean + readOnly: true + examples: + - true + picture: + description: >- + The URL to the user's profile picture or avatar image. This field stores + the location of the user's profile photo that appears in user interfaces, + directory listings, and collaborative features throughout the system. The + URL should point to a publicly accessible image file. Supported formats + typically include JPEG, PNG, and GIF. This image is used for visual + identification and personalization across the platform. + type: string + examples: + - https://example.com/avatar.jpg + preferred_username: + description: >- + The user's preferred username for display and identification purposes. + This field stores a custom username that the user prefers to be known by, + which may differ from their email or formal name. This username appears in + user interfaces, mentions, informal communications, and collaborative + features throughout the system. Maximum 512 characters allowed. + type: string + examples: + - johndoe diff --git a/openapi/components/schemas/connected_accountsAuthorizationDetails.yaml b/openapi/components/schemas/connected_accountsAuthorizationDetails.yaml new file mode 100644 index 000000000..a892527ef --- /dev/null +++ b/openapi/components/schemas/connected_accountsAuthorizationDetails.yaml @@ -0,0 +1,12 @@ +type: object +title: Authentication credentials container supporting multiple auth types +properties: + google_dwd: + title: Google Domain-Wide Delegation credentials + $ref: ./connected_accountsGoogleDWDAuth.yaml + oauth_token: + title: OAuth 2.0 credentials + $ref: ./connected_accountsOauthToken.yaml + static_auth: + title: Static authentication credentials + $ref: ./connected_accountsStaticAuth.yaml diff --git a/openapi/components/schemas/connected_accountsConnectedAccount.yaml b/openapi/components/schemas/connected_accountsConnectedAccount.yaml new file mode 100644 index 000000000..d970821cf --- /dev/null +++ b/openapi/components/schemas/connected_accountsConnectedAccount.yaml @@ -0,0 +1,86 @@ +type: object +properties: + api_config: + description: >- + Optional JSON configuration for connector-specific API settings such as + rate limits, custom endpoints, or feature flags. + type: object + examples: + - base_url: https://api.custom-domain.com + rate_limit: 1000 + timeout: 30 + authorization_details: + description: >- + Sensitive authentication credentials including access tokens, refresh + tokens, and scopes. Contains either OAuth tokens or static auth details. + $ref: ./connected_accountsAuthorizationDetails.yaml + authorization_type: + description: >- + Type of authorization mechanism used. Specifies whether this connection + uses OAuth, API keys, bearer tokens, or other auth methods. + $ref: ./connected_accountsConnectorType.yaml + connection_id: + description: >- + Reference to the parent connection configuration. Links this account to a + specific connector setup in your environment. + type: string + examples: + - conn_24834495392086178 + connector: + description: >- + Connector identifier (e.g., 'notion', 'slack', 'salesforce'). Indicates + which third-party application this account connects to. + type: string + examples: + - notion + id: + description: >- + Unique Scalekit-generated identifier for this connected account. Always + prefixed with 'ca_'. + type: string + examples: + - ca_24834495392086178 + identifier: + description: >- + The unique identifier for this account in the third-party service. + Typically an email address, user ID, or workspace identifier. + type: string + examples: + - user@example.com + last_used_at: + description: >- + Timestamp when this connected account was last used to make an API call. + Useful for tracking active connections. + type: string + format: date-time + examples: + - '2024-03-20T14:30:00Z' + provider: + description: >- + OAuth provider name (e.g., 'google', 'microsoft', 'github'). Identifies + which authentication service manages this connection. + type: string + examples: + - google + status: + description: >- + Current status of the connected account. Indicates if the account is + active, expired, pending authorization, or pending user identity + verification. + $ref: ./connected_accountsConnectorStatus.yaml + token_expires_at: + description: >- + Expiration timestamp for the access token. After this time, the token must + be refreshed or re-authorized. + type: string + format: date-time + examples: + - '2024-12-31T23:59:59Z' + updated_at: + description: >- + Timestamp when this connected account was last modified. Updated whenever + credentials or configuration changes. + type: string + format: date-time + examples: + - '2024-03-20T15:04:05Z' diff --git a/openapi/components/schemas/connected_accountsConnectedAccountForList.yaml b/openapi/components/schemas/connected_accountsConnectedAccountForList.yaml new file mode 100644 index 000000000..984b7eb53 --- /dev/null +++ b/openapi/components/schemas/connected_accountsConnectedAccountForList.yaml @@ -0,0 +1,54 @@ +type: object +title: >- + Connected account summary for list operations - excludes sensitive + authorization details +properties: + authorization_type: + description: Authorization mechanism type. + $ref: ./connected_accountsConnectorType.yaml + connection_id: + description: Parent connection configuration reference. + type: string + examples: + - conn_24834495392086178 + connector: + description: Connector identifier. + type: string + examples: + - notion + id: + description: Unique connected account identifier. + type: string + examples: + - ca_24834495392086178 + identifier: + description: The unique identifier for this account in the third-party service. + type: string + examples: + - user@example.com + last_used_at: + description: Last usage timestamp. + type: string + format: date-time + examples: + - '2024-03-20T14:30:00Z' + provider: + description: OAuth provider name (e.g., 'google', 'microsoft'). + type: string + examples: + - google + status: + description: Current connection status. + $ref: ./connected_accountsConnectorStatus.yaml + token_expires_at: + description: Token expiration timestamp. + type: string + format: date-time + examples: + - '2024-12-31T23:59:59Z' + updated_at: + description: Last modification timestamp. + type: string + format: date-time + examples: + - '2024-03-20T15:04:05Z' diff --git a/openapi/components/schemas/connected_accountsConnectorStatus.yaml b/openapi/components/schemas/connected_accountsConnectorStatus.yaml new file mode 100644 index 000000000..575134b19 --- /dev/null +++ b/openapi/components/schemas/connected_accountsConnectorStatus.yaml @@ -0,0 +1,15 @@ +description: |- + - ACTIVE: Account is connected and credentials are valid + - EXPIRED: Access token has expired and needs refresh + - PENDING_AUTH: Account awaiting user authorization (re-auth initiated) + - PENDING_VERIFICATION: OAuth complete; awaiting user identity verification + before activation + - DISCONNECTED: Account has been manually disconnected +type: string +title: Status of a connected account indicating its current state +enum: + - ACTIVE + - EXPIRED + - PENDING_AUTH + - PENDING_VERIFICATION + - DISCONNECTED diff --git a/openapi/components/schemas/connected_accountsConnectorType.yaml b/openapi/components/schemas/connected_accountsConnectorType.yaml new file mode 100644 index 000000000..41cfdf85c --- /dev/null +++ b/openapi/components/schemas/connected_accountsConnectorType.yaml @@ -0,0 +1,22 @@ +description: |- + - OAUTH: OAuth 2.0 authorization with access and refresh tokens + - API_KEY: Static API key authentication + - BASIC_AUTH: HTTP Basic Authentication (username/password) + - BEARER_TOKEN: Bearer token authentication + - CUSTOM: Custom authentication mechanism + - BASIC: Basic authentication (alias) + - OAUTH_M2M: OAuth 2.0 client credentials (machine-to-machine) + - TRELLO_OAUTH1: Trello token-based OAuth1-style browser authorization + - GOOGLE_DWD: Google Domain-Wide Delegation +type: string +title: Type of authentication mechanism used for the connected account +enum: + - OAUTH + - API_KEY + - BASIC_AUTH + - BEARER_TOKEN + - CUSTOM + - BASIC + - OAUTH_M2M + - TRELLO_OAUTH1 + - GOOGLE_DWD diff --git a/openapi/components/schemas/connected_accountsCreateConnectedAccountRequest.yaml b/openapi/components/schemas/connected_accountsCreateConnectedAccountRequest.yaml new file mode 100644 index 000000000..ebd66307b --- /dev/null +++ b/openapi/components/schemas/connected_accountsCreateConnectedAccountRequest.yaml @@ -0,0 +1,38 @@ +type: object +properties: + connected_account: + description: Details of the connected account to create + $ref: ./v1connected_accountsCreateConnectedAccount.yaml + examples: + - authorization_details: + oauth_token: + access_token: ... + refresh_token: ... + scopes: + - read + - write + authorization_type: OAUTH2 + connector: + description: >- + Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric + characters, spaces, hyphens, underscores, and colons are allowed. + type: string + examples: + - notion + identifier: + description: >- + The unique identifier for the connected account within the third-party + service (e.g., email address, user ID, workspace identifier). + type: string + examples: + - user@example.com + organization_id: + description: Organization ID for the connector + type: string + examples: + - org_121312434123312 + user_id: + description: User ID for the connector + type: string + examples: + - user_121312434123312 diff --git a/openapi/components/schemas/connected_accountsCreateConnectedAccountResponse.yaml b/openapi/components/schemas/connected_accountsCreateConnectedAccountResponse.yaml new file mode 100644 index 000000000..6d6b28799 --- /dev/null +++ b/openapi/components/schemas/connected_accountsCreateConnectedAccountResponse.yaml @@ -0,0 +1,7 @@ +type: object +properties: + connected_account: + description: >- + The newly created connected account with its unique identifier, status, + and complete authorization details including access tokens. + $ref: ./connected_accountsConnectedAccount.yaml diff --git a/openapi/components/schemas/connected_accountsDeleteConnectedAccountRequest.yaml b/openapi/components/schemas/connected_accountsDeleteConnectedAccountRequest.yaml new file mode 100644 index 000000000..c4bcbd888 --- /dev/null +++ b/openapi/components/schemas/connected_accountsDeleteConnectedAccountRequest.yaml @@ -0,0 +1,31 @@ +type: object +properties: + connector: + description: >- + Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric + characters, spaces, hyphens, underscores, and colons are allowed. + type: string + examples: + - notion + id: + description: Unique identifier for the connected account to delete + type: string + examples: + - ca_123 + identifier: + description: >- + The unique identifier for the connected account within the third-party + service (e.g., email address, user ID, workspace identifier). + type: string + examples: + - user@example.com + organization_id: + description: Organization ID for the connector + type: string + examples: + - org_121312434123312 + user_id: + description: User ID for the connector + type: string + examples: + - user_121312434123312 diff --git a/openapi/components/schemas/connected_accountsDeleteConnectedAccountResponse.yaml b/openapi/components/schemas/connected_accountsDeleteConnectedAccountResponse.yaml new file mode 100644 index 000000000..91bf3091f --- /dev/null +++ b/openapi/components/schemas/connected_accountsDeleteConnectedAccountResponse.yaml @@ -0,0 +1 @@ +type: object diff --git a/openapi/components/schemas/connected_accountsGetConnectedAccountByIdentifierResponse.yaml b/openapi/components/schemas/connected_accountsGetConnectedAccountByIdentifierResponse.yaml new file mode 100644 index 000000000..a11099d70 --- /dev/null +++ b/openapi/components/schemas/connected_accountsGetConnectedAccountByIdentifierResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + connected_account: + description: >- + The connected account with complete details including sensitive + authorization credentials (access tokens, refresh tokens, scopes). Handle + with appropriate access controls. + $ref: ./connected_accountsConnectedAccount.yaml diff --git a/openapi/components/schemas/connected_accountsGetMagicLinkForConnectedAccountRequest.yaml b/openapi/components/schemas/connected_accountsGetMagicLinkForConnectedAccountRequest.yaml new file mode 100644 index 000000000..ecbea3d2c --- /dev/null +++ b/openapi/components/schemas/connected_accountsGetMagicLinkForConnectedAccountRequest.yaml @@ -0,0 +1,43 @@ +type: object +properties: + connector: + description: >- + Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric + characters, spaces, hyphens, underscores, and colons are allowed. + type: string + examples: + - notion + id: + description: Unique identifier for the connected account + type: string + examples: + - ca_123 + identifier: + description: >- + The unique identifier for the connected account within the third-party + service (e.g., email address, user ID, workspace identifier). + type: string + examples: + - user@example.com + organization_id: + description: Organization ID for the connector + type: string + examples: + - org_121312434123312 + state: + description: >- + Optional opaque state value. State added to the user verify redirect URL + query params to validate the user verification + type: string + examples: + - QVNDSUFyY2hhYml0dGVyXzE2ODQ5NzIwNzI0NTY= + user_id: + description: User ID for the connector + type: string + examples: + - user_121312434123312 + user_verify_url: + description: B2B app's user verify redirect URL + type: string + examples: + - https://app.yourapp.com/user/verify/callback diff --git a/openapi/components/schemas/connected_accountsGetMagicLinkForConnectedAccountResponse.yaml b/openapi/components/schemas/connected_accountsGetMagicLinkForConnectedAccountResponse.yaml new file mode 100644 index 000000000..78dcabb24 --- /dev/null +++ b/openapi/components/schemas/connected_accountsGetMagicLinkForConnectedAccountResponse.yaml @@ -0,0 +1,13 @@ +type: object +properties: + expiry: + description: Expiry timestamp for the authentication link + type: string + format: date-time + examples: + - '2024-03-20T15:04:05Z' + link: + description: Authentication link for the connector + type: string + examples: + - https://notion.com/oauth/authorize?client_id=... diff --git a/openapi/components/schemas/connected_accountsGoogleDWDAuth.yaml b/openapi/components/schemas/connected_accountsGoogleDWDAuth.yaml new file mode 100644 index 000000000..f7d1ae7e6 --- /dev/null +++ b/openapi/components/schemas/connected_accountsGoogleDWDAuth.yaml @@ -0,0 +1,37 @@ +description: >- + Google Domain-Wide Delegation authentication — used for GOOGLE_DWD + connections. + + Send only subject in requests; access_token, scopes, and token_expires_at are + response-only. +type: object +properties: + access_token: + description: >- + OAuth access token acquired via the jwt-bearer grant. Present in responses + only. + type: string + readOnly: true + examples: + - ya29.a0AfH6SMBx... + scopes: + description: OAuth scopes granted to this token. Present in responses only. + type: array + items: + type: string + readOnly: true + examples: + - - openid + - https://www.googleapis.com/auth/userinfo.email + subject: + description: >- + Email address of the Google Workspace user to impersonate via Domain-Wide + Delegation. + type: string + examples: + - user@example.com + token_expires_at: + description: When the access token expires. Present in responses only. + type: string + format: date-time + readOnly: true diff --git a/openapi/components/schemas/connected_accountsListConnectedAccountsResponse.yaml b/openapi/components/schemas/connected_accountsListConnectedAccountsResponse.yaml new file mode 100644 index 000000000..a30b5e74e --- /dev/null +++ b/openapi/components/schemas/connected_accountsListConnectedAccountsResponse.yaml @@ -0,0 +1,32 @@ +type: object +properties: + connected_accounts: + description: >- + List of connected accounts matching the filter criteria. Excludes + sensitive authorization details for security. + type: array + items: + type: object + $ref: ./connected_accountsConnectedAccountForList.yaml + next_page_token: + description: >- + Pagination token for retrieving the next page. Empty if this is the last + page. Pass this value to page_token in the next request. + type: string + examples: + - eyJvZmZzZXQiOjIwfQ== + prev_page_token: + description: >- + Pagination token for retrieving the previous page. Empty if this is the + first page. Pass this value to page_token to go back. + type: string + examples: + - eyJvZmZzZXQiOjB9 + total_size: + description: >- + Total count of connected accounts matching the filter criteria across all + pages. Use for calculating pagination. + type: integer + format: int64 + examples: + - 100 diff --git a/openapi/components/schemas/connected_accountsOauthToken.yaml b/openapi/components/schemas/connected_accountsOauthToken.yaml new file mode 100644 index 000000000..2105aaffa --- /dev/null +++ b/openapi/components/schemas/connected_accountsOauthToken.yaml @@ -0,0 +1,34 @@ +type: object +title: OAuth 2.0 access and refresh tokens with scopes +properties: + access_token: + description: >- + OAuth access token for API requests. Typically short-lived and must be + refreshed after expiration. + type: string + examples: + - ya29.a0AfH6SMBx... + domain: + description: >- + Associated domain for workspace or organization-scoped OAuth connections + (e.g., Google Workspace domain). + type: string + examples: + - example.com + refresh_token: + description: >- + OAuth refresh token for obtaining new access tokens. Long-lived and used + to maintain persistent authorization. + type: string + examples: + - 1//0gHJxZ-Lb2... + scopes: + description: >- + List of granted OAuth scopes defining the permissions and access levels + for this connection. + type: array + items: + type: string + examples: + - - https://www.googleapis.com/auth/drive.readonly + - https://www.googleapis.com/auth/userinfo.email diff --git a/openapi/components/schemas/connected_accountsSearchConnectedAccountsResponse.yaml b/openapi/components/schemas/connected_accountsSearchConnectedAccountsResponse.yaml new file mode 100644 index 000000000..5362c7bb4 --- /dev/null +++ b/openapi/components/schemas/connected_accountsSearchConnectedAccountsResponse.yaml @@ -0,0 +1,26 @@ +type: object +properties: + connected_accounts: + description: >- + List of connected accounts matching the search query. Excludes sensitive + authorization details. + type: array + items: + type: object + $ref: ./connected_accountsConnectedAccountForList.yaml + next_page_token: + description: Pagination token for the next page. Empty if this is the last page. + type: string + examples: + - eyJvZmZzZXQiOjMwfQ== + prev_page_token: + description: Pagination token for the previous page. Empty if this is the first page. + type: string + examples: + - eyJvZmZzZXQiOjB9 + total_size: + description: Total count of accounts matching the search query across all pages. + type: integer + format: int64 + examples: + - 100 diff --git a/openapi/components/schemas/connected_accountsStaticAuth.yaml b/openapi/components/schemas/connected_accountsStaticAuth.yaml new file mode 100644 index 000000000..3034fa803 --- /dev/null +++ b/openapi/components/schemas/connected_accountsStaticAuth.yaml @@ -0,0 +1,11 @@ +type: object +title: Static authentication credentials for API keys, bearer tokens, or basic auth +properties: + details: + description: >- + Flexible JSON structure containing static credentials. Format varies by + connector type (API key, username/password, etc.). + type: object + examples: + - api_key: sk_live_... + api_secret: ... diff --git a/openapi/components/schemas/connected_accountsUpdateConnectedAccountRequest.yaml b/openapi/components/schemas/connected_accountsUpdateConnectedAccountRequest.yaml new file mode 100644 index 000000000..5b0968121 --- /dev/null +++ b/openapi/components/schemas/connected_accountsUpdateConnectedAccountRequest.yaml @@ -0,0 +1,43 @@ +type: object +properties: + connected_account: + description: Details of the connected account to update + $ref: ./v1connected_accountsUpdateConnectedAccount.yaml + examples: + - authorization_details: + oauth_token: + access_token: ... + refresh_token: ... + scopes: + - read + - write + authorization_type: OAUTH2 + connector: + description: >- + Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric + characters, spaces, hyphens, underscores, and colons are allowed. + type: string + examples: + - notion + id: + description: Unique identifier for the connected account to update + type: string + examples: + - ca_123 + identifier: + description: >- + The unique identifier for the connected account within the third-party + service (e.g., email address, user ID, workspace identifier). + type: string + examples: + - user@example.com + organization_id: + description: Organization ID for the connector + type: string + examples: + - org_121312434123312 + user_id: + description: User ID for the connector + type: string + examples: + - user_121312434123312 diff --git a/openapi/components/schemas/connected_accountsUpdateConnectedAccountResponse.yaml b/openapi/components/schemas/connected_accountsUpdateConnectedAccountResponse.yaml new file mode 100644 index 000000000..e309a403e --- /dev/null +++ b/openapi/components/schemas/connected_accountsUpdateConnectedAccountResponse.yaml @@ -0,0 +1,7 @@ +type: object +properties: + connected_account: + description: >- + The updated connected account with refreshed credentials, new token + expiry, and modified configuration settings. + $ref: ./connected_accountsConnectedAccount.yaml diff --git a/openapi/components/schemas/connected_accountsVerifyConnectedAccountUserRequest.yaml b/openapi/components/schemas/connected_accountsVerifyConnectedAccountUserRequest.yaml new file mode 100644 index 000000000..b193bdaf9 --- /dev/null +++ b/openapi/components/schemas/connected_accountsVerifyConnectedAccountUserRequest.yaml @@ -0,0 +1,17 @@ +type: object +required: + - auth_request_id + - identifier +properties: + auth_request_id: + description: >- + Auth request ID as base64url-encoded opaque token from the user verify + redirect URL query params + type: string + examples: + - QVNDSUFyY2hhYml0dGVyXzE2ODQ5NzIwNzI0NTY= + identifier: + description: Current logged in user's connected account identifier + type: string + examples: + - user@example.com diff --git a/openapi/components/schemas/connected_accountsVerifyConnectedAccountUserResponse.yaml b/openapi/components/schemas/connected_accountsVerifyConnectedAccountUserResponse.yaml new file mode 100644 index 000000000..bc71614be --- /dev/null +++ b/openapi/components/schemas/connected_accountsVerifyConnectedAccountUserResponse.yaml @@ -0,0 +1,7 @@ +type: object +properties: + post_user_verify_redirect_url: + description: URL to redirect the user to after successful verification + type: string + examples: + - https://env1.example.com/connect/success diff --git a/openapi/components/schemas/connectionsCodeChallengeType.yaml b/openapi/components/schemas/connectionsCodeChallengeType.yaml new file mode 100644 index 000000000..b6e390e55 --- /dev/null +++ b/openapi/components/schemas/connectionsCodeChallengeType.yaml @@ -0,0 +1,4 @@ +type: string +enum: + - NUMERIC + - ALPHANUMERIC diff --git a/openapi/components/schemas/connectionsConfigurationType.yaml b/openapi/components/schemas/connectionsConfigurationType.yaml new file mode 100644 index 000000000..49ed1e2e4 --- /dev/null +++ b/openapi/components/schemas/connectionsConfigurationType.yaml @@ -0,0 +1,4 @@ +type: string +enum: + - DISCOVERY + - MANUAL diff --git a/openapi/components/schemas/connectionsConnection.yaml b/openapi/components/schemas/connectionsConnection.yaml new file mode 100644 index 000000000..e0f6b74b5 --- /dev/null +++ b/openapi/components/schemas/connectionsConnection.yaml @@ -0,0 +1,128 @@ +type: object +properties: + attribute_mapping: + description: >- + Maps identity provider attributes to user profile fields. For example, + {'email': 'user.mail', 'name': 'user.displayName'}. + type: object + additionalProperties: + type: string + configuration_type: + description: >- + How the connection was configured: DISCOVERY (automatic configuration) or + MANUAL (administrator configured) + $ref: ./connectionsConfigurationType.yaml + examples: + - MANUAL + debug_enabled: + description: >- + Enables testing mode that allows non-HTTPS endpoints. Should only be + enabled in development environments, never in production. + type: boolean + examples: + - true + domains: + description: >- + Domain associated with this connection, used for domain-based + authentication flows. + type: array + items: + type: object + $ref: ./domainsDomain.yaml + examples: + - - name: example.com + enabled: + description: >- + Controls whether users can sign in using this connection. When false, the + connection exists but cannot be used for authentication. + type: boolean + examples: + - false + google_dwd_config: + description: >- + Configuration details for Google Domain-Wide Delegation. Present only when + type is GOOGLE_DWD. + $ref: ./connectionsGoogleDWDConfig.yaml + id: + description: >- + Unique identifier for this connection. Used in API calls to reference this + specific connection. + type: string + examples: + - conn_2123312131125533 + key_id: + description: >- + Alternative identifier for this connection, typically used in frontend + applications or URLs. + type: string + oauth_config: + description: >- + Configuration details for OAuth connections. Present only when type is + OAUTH. + $ref: ./connectionsOAuthConnectionConfig.yaml + oidc_config: + description: >- + Configuration details for OpenID Connect (OIDC) connections. Present only + when type is OIDC. + $ref: ./connectionsOIDCConnectionConfig.yaml + organization_id: + description: >- + Identifier of the organization that owns this connection. Connections are + typically scoped to a single organization. + type: string + examples: + - org_2123312131125533 + passwordless_config: + description: >- + Configuration details for Magic Link authentication. Present only when + type is MAGIC_LINK. + $ref: ./connectionsPasswordLessConfig.yaml + provider: + description: >- + Identity provider service that handles authentication (such as OKTA, + Google, Azure AD, or a custom provider) + $ref: ./connectionsConnectionProvider.yaml + examples: + - OKTA + provider_key: + description: Key ID of the identity provider service that handles authentication + type: string + examples: + - google + saml_config: + description: >- + Configuration details for SAML connections. Present only when type is + SAML. + $ref: ./connectionsSAMLConnectionConfigResponse.yaml + static_config: + description: >- + Static configuration for custom connections. Present only when type is + BASIC, BEARER, API_KEY, or custom. + $ref: ./connectionsStaticAuthConfig.yaml + status: + description: >- + Current configuration status of the connection. Possible values include + IN_PROGRESS, CONFIGURED, and ERROR. + $ref: ./connectionsConnectionStatus.yaml + readOnly: true + examples: + - IN_PROGRESS + test_connection_uri: + description: >- + URI that can be used to test this connection. Visit this URL to verify the + connection works correctly. + type: string + examples: + - https://auth.example.com/test-connection/conn_2123312131125533 + type: + description: >- + Authentication protocol used by this connection. Can be OIDC (OpenID + Connect), SAML, OAUTH, or MAGIC_LINK. + $ref: ./connectionsConnectionType.yaml + examples: + - OIDC + webauthn_config: + description: >- + Configuration details for WebAuthn (passkeys). Present only when type is + WEBAUTHN. + $ref: ./connectionsWebAuthConfiguration.yaml diff --git a/openapi/components/schemas/connectionsConnectionProvider.yaml b/openapi/components/schemas/connectionsConnectionProvider.yaml new file mode 100644 index 000000000..5f6b76ebc --- /dev/null +++ b/openapi/components/schemas/connectionsConnectionProvider.yaml @@ -0,0 +1,18 @@ +type: string +enum: + - OKTA + - GOOGLE + - MICROSOFT_AD + - AUTH0 + - ONELOGIN + - PING_IDENTITY + - JUMPCLOUD + - CUSTOM + - GITHUB + - GITLAB + - LINKEDIN + - SALESFORCE + - MICROSOFT + - IDP_SIMULATOR + - SCALEKIT + - ADFS diff --git a/openapi/components/schemas/connectionsConnectionStatus.yaml b/openapi/components/schemas/connectionsConnectionStatus.yaml new file mode 100644 index 000000000..bc55c7349 --- /dev/null +++ b/openapi/components/schemas/connectionsConnectionStatus.yaml @@ -0,0 +1,5 @@ +type: string +enum: + - DRAFT + - IN_PROGRESS + - COMPLETED diff --git a/openapi/components/schemas/connectionsConnectionType.yaml b/openapi/components/schemas/connectionsConnectionType.yaml new file mode 100644 index 000000000..b040b2009 --- /dev/null +++ b/openapi/components/schemas/connectionsConnectionType.yaml @@ -0,0 +1,14 @@ +type: string +enum: + - OIDC + - SAML + - PASSWORD + - OAUTH + - PASSWORDLESS + - BASIC + - BEARER + - API_KEY + - WEBAUTHN + - OAUTH_M2M + - TRELLO_OAUTH1 + - GOOGLE_DWD diff --git a/openapi/components/schemas/connectionsGetConnectionResponse.yaml b/openapi/components/schemas/connectionsGetConnectionResponse.yaml new file mode 100644 index 000000000..82104c7ea --- /dev/null +++ b/openapi/components/schemas/connectionsGetConnectionResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + connection: + description: >- + Complete connection details including provider configuration, protocol + settings, status, and all metadata. Contains everything needed to + understand the connection's current state. + $ref: ./connectionsConnection.yaml diff --git a/openapi/components/schemas/connectionsGoogleDWDConfig.yaml b/openapi/components/schemas/connectionsGoogleDWDConfig.yaml new file mode 100644 index 000000000..466b0a7a4 --- /dev/null +++ b/openapi/components/schemas/connectionsGoogleDWDConfig.yaml @@ -0,0 +1,15 @@ +type: object +properties: + scopes: + description: OAuth 2.0 scopes to request. + type: array + items: + type: string + service_account_json: + description: >- + Google Cloud service account JSON key. Write-only: reads return a masked + value. + type: string + token_uri: + description: Google token endpoint. Defaults to https://oauth2.googleapis.com/token. + type: string diff --git a/openapi/components/schemas/connectionsIDPCertificate.yaml b/openapi/components/schemas/connectionsIDPCertificate.yaml new file mode 100644 index 000000000..768887e4c --- /dev/null +++ b/openapi/components/schemas/connectionsIDPCertificate.yaml @@ -0,0 +1,27 @@ +type: object +properties: + certificate: + description: IDP Certificate + type: string + create_time: + description: Certificate Creation Time + type: string + format: date-time + examples: + - '2021-09-01T00:00:00Z' + expiry_time: + description: Certificate Expiry Time + type: string + format: date-time + examples: + - '2021-09-01T00:00:00Z' + id: + description: Certificate ID + type: string + examples: + - cert_123123123123 + issuer: + description: Certificate Issuer + type: string + examples: + - https://youridp.com/service/saml diff --git a/openapi/components/schemas/connectionsListConnection.yaml b/openapi/components/schemas/connectionsListConnection.yaml new file mode 100644 index 000000000..8b1179d5c --- /dev/null +++ b/openapi/components/schemas/connectionsListConnection.yaml @@ -0,0 +1,58 @@ +type: object +properties: + domains: + description: List of domains configured with this connection + type: array + items: + type: string + examples: + - - yourapp.com + - yourworkspace.com + enabled: + description: Whether the connection is currently active for organization users + type: boolean + examples: + - false + id: + description: Unique identifier of the connection + type: string + examples: + - conn_2123312131125533 + key_id: + description: >- + Alternative identifier for this connection, typically used in frontend + applications or URLs + type: string + examples: + - conn_2123312131125533 + organization_id: + description: Unique identifier of the organization that owns this connection + type: string + examples: + - org_2123312131125533 + organization_name: + description: Name of the organization of the connection + type: string + examples: + - Your Organization + provider: + description: Identity provider type (e.g., OKTA, Google, Azure AD) + $ref: ./connectionsConnectionProvider.yaml + examples: + - CUSTOM + provider_key: + description: Key ID of the identity provider service that handles authentication + type: string + examples: + - google + status: + description: Current configuration status of the connection + $ref: ./connectionsConnectionStatus.yaml + readOnly: true + examples: + - IN_PROGRESS + type: + description: Authentication protocol used by the connection + $ref: ./connectionsConnectionType.yaml + examples: + - OIDC diff --git a/openapi/components/schemas/connectionsListConnectionsResponse.yaml b/openapi/components/schemas/connectionsListConnectionsResponse.yaml new file mode 100644 index 000000000..964d03297 --- /dev/null +++ b/openapi/components/schemas/connectionsListConnectionsResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + connections: + description: List of connections matching the request criteria + type: array + items: + type: object + $ref: ./connectionsListConnection.yaml diff --git a/openapi/components/schemas/connectionsNameIdFormat.yaml b/openapi/components/schemas/connectionsNameIdFormat.yaml new file mode 100644 index 000000000..28a5fced7 --- /dev/null +++ b/openapi/components/schemas/connectionsNameIdFormat.yaml @@ -0,0 +1,6 @@ +type: string +enum: + - UNSPECIFIED + - EMAIL + - TRANSIENT + - PERSISTENT diff --git a/openapi/components/schemas/connectionsOAuthConnectionConfig.yaml b/openapi/components/schemas/connectionsOAuthConnectionConfig.yaml new file mode 100644 index 000000000..29340e03a --- /dev/null +++ b/openapi/components/schemas/connectionsOAuthConnectionConfig.yaml @@ -0,0 +1,106 @@ +type: object +properties: + access_type: + description: Access Type + type: string + examples: + - offline + app_name: + description: >- + Application name used by providers that require it as an authorize query + parameter (e.g., Trello's app_name). + type: string + examples: + - My Trello App + authorize_uri: + description: Authorize URI + type: string + examples: + - https://youridp.com/service/oauth/authorize + client_id: + description: Client ID + type: string + examples: + - oauth_client_id + client_secret: + description: Client Secret + type: string + examples: + - oauth_client_secret + custom_scope_name: + description: Custom Scope Name + type: string + examples: + - user_scope + is_cimd: + description: >- + Indicates whether this connection was registered using Client ID Metadata + Document (CIMD) instead of Dynamic Client Registration. + type: boolean + readOnly: true + examples: + - true + optional_scopes: + description: >- + Optional scopes configuration for identity providers that support or + require additional scopes to be sent in a custom field during + authentication requests. + $ref: ./connectionsOptionalScopes.yaml + pkce_enabled: + description: PKCE Enabled + type: boolean + examples: + - true + prompt: + description: Prompt for the user + type: string + examples: + - none + redirect_uri: + description: Redirect URI + type: string + examples: + - https://yourapp.com/service/oauth/redirect + scopes: + description: OIDC Scopes + type: array + items: + type: string + examples: + - - openid + - profile + sync_user_profile_on_login: + description: >- + Indicates whether user profiles should be synchronized with the identity + provider upon each log-in. + type: boolean + examples: + - true + tenant_id: + description: >- + Microsoft Entra tenant ID. Required when using a single-tenant or + multi-tenant app registered in Microsoft Entra. Leave empty to use the + common endpoint. + type: string + examples: + - xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + token_access_type: + description: Token Access Type + type: string + examples: + - offline + token_uri: + description: Token URI + type: string + examples: + - https://youridp.com/service/oauth/token + use_platform_creds: + description: Use Scalekit credentials + type: boolean + examples: + - true + user_info_uri: + description: User Info URI + type: string + examples: + - https://youridp.com/service/oauth/userinfo diff --git a/openapi/components/schemas/connectionsOIDCConnectionConfig.yaml b/openapi/components/schemas/connectionsOIDCConnectionConfig.yaml new file mode 100644 index 000000000..3b4a12ae8 --- /dev/null +++ b/openapi/components/schemas/connectionsOIDCConnectionConfig.yaml @@ -0,0 +1,94 @@ +type: object +properties: + authorize_uri: + description: Authorize URI + type: string + examples: + - https://youridp.com/service/oauth/authorize + backchannel_logout_redirect_uri: + description: backchannel logout redirect uri where idp sends logout_token + type: string + readOnly: true + examples: + - https://yourapp.com/sso/v1/oidc/conn_1234/backchannel-logout + client_id: + description: Client ID + type: string + examples: + - oauth_client_id + client_secret: + description: Client Secret + type: string + examples: + - oauth_client_secret + discovery_endpoint: + description: Discovery Endpoint + type: string + examples: + - https://youridp.com/service/oauth/.well-known/openid-configuration + idp_logout_required: + description: Enable IDP logout + type: boolean + examples: + - true + issuer: + description: Issuer URL + type: string + examples: + - https://youridp.com/service/oauth + jit_provisioning_with_sso_enabled: + description: Indicates if Just In Time user provisioning is enabled for the connection + type: boolean + examples: + - true + jwks_uri: + description: JWKS URI + type: string + examples: + - https://youridp.com/service/oauth/jwks + pkce_enabled: + description: PKCE Enabled + type: boolean + examples: + - true + post_logout_redirect_uri: + description: post logout redirect uri + type: string + readOnly: true + examples: + - https://yourapp.com/sso/v1/oidc/conn_1234/logout/callback + redirect_uri: + description: Redirect URI + type: string + examples: + - https://yourapp.com/sso/v1/oidc/conn_1234/callback + scopes: + description: OIDC Scopes + type: array + items: + $ref: ./connectionsOIDCScope.yaml + examples: + - - openid + - profile + sync_user_profile_on_login: + description: >- + Indicates whether user profiles should be synchronized with the identity + provider upon each log-in. + type: boolean + examples: + - true + token_auth_type: + description: Token Auth Type + $ref: ./connectionsTokenAuthType.yaml + examples: + - URL_PARAMS + token_uri: + description: Token URI + type: string + examples: + - https://youridp.com/service/oauth/token + user_info_uri: + description: User Info URI + type: string + examples: + - https://youridp.com/service/oauth/userinfo diff --git a/openapi/components/schemas/connectionsOIDCScope.yaml b/openapi/components/schemas/connectionsOIDCScope.yaml new file mode 100644 index 000000000..886f6120d --- /dev/null +++ b/openapi/components/schemas/connectionsOIDCScope.yaml @@ -0,0 +1,7 @@ +type: string +enum: + - openid + - profile + - email + - address + - phone diff --git a/openapi/components/schemas/connectionsOptionalScopes.yaml b/openapi/components/schemas/connectionsOptionalScopes.yaml new file mode 100644 index 000000000..cf8ea0f5a --- /dev/null +++ b/openapi/components/schemas/connectionsOptionalScopes.yaml @@ -0,0 +1,18 @@ +type: object +properties: + field_name: + description: >- + Name of the field in which scope should be sent in the authentication + request. This is required by some identity providers that expect scopes to + be sent in a custom field instead of the standard 'scope' parameter. + type: string + examples: + - optional_scope or bot_scope + scopes: + description: List of optional scopes that can be requested during authentication + type: array + items: + type: string + examples: + - - scope1 + - scope2 diff --git a/openapi/components/schemas/connectionsPasswordLessConfig.yaml b/openapi/components/schemas/connectionsPasswordLessConfig.yaml new file mode 100644 index 000000000..56fcb7f50 --- /dev/null +++ b/openapi/components/schemas/connectionsPasswordLessConfig.yaml @@ -0,0 +1,40 @@ +type: object +properties: + code_challenge_length: + description: Code Challenge Length + type: integer + format: int64 + examples: + - 6 + code_challenge_type: + description: Code Challenge Type + $ref: ./connectionsCodeChallengeType.yaml + examples: + - NUMERIC + enforce_same_browser_origin: + description: Enforce Same Browser Origin + type: boolean + examples: + - true + frequency: + description: Link Frequency + type: integer + format: int64 + examples: + - 1 + regenerate_passwordless_credentials_on_resend: + description: 'Regenerate the ' + type: boolean + examples: + - true + type: + description: Passwordless Type + $ref: ./connectionsPasswordlessType.yaml + examples: + - LINK + validity: + description: Link Validity in Seconds + type: integer + format: int64 + examples: + - 600 diff --git a/openapi/components/schemas/connectionsPasswordlessType.yaml b/openapi/components/schemas/connectionsPasswordlessType.yaml new file mode 100644 index 000000000..10fd39e86 --- /dev/null +++ b/openapi/components/schemas/connectionsPasswordlessType.yaml @@ -0,0 +1,5 @@ +type: string +enum: + - LINK + - OTP + - LINK_OTP diff --git a/openapi/components/schemas/connectionsRequestBinding.yaml b/openapi/components/schemas/connectionsRequestBinding.yaml new file mode 100644 index 000000000..52341f8b3 --- /dev/null +++ b/openapi/components/schemas/connectionsRequestBinding.yaml @@ -0,0 +1,4 @@ +type: string +enum: + - HTTP_POST + - HTTP_REDIRECT diff --git a/openapi/components/schemas/connectionsSAMLConnectionConfigResponse.yaml b/openapi/components/schemas/connectionsSAMLConnectionConfigResponse.yaml new file mode 100644 index 000000000..36617193f --- /dev/null +++ b/openapi/components/schemas/connectionsSAMLConnectionConfigResponse.yaml @@ -0,0 +1,121 @@ +type: object +properties: + allow_idp_initiated_login: + description: Allow IDP Initiated Login + type: boolean + examples: + - true + assertion_encrypted: + description: Assertion Encrypted + type: boolean + examples: + - true + certificate_id: + description: Certificate ID + type: string + examples: + - cer_35585423166144613 + default_redirect_uri: + description: Default Redirect URI + type: string + examples: + - https://yourapp.com/service/saml/redirect + force_authn: + description: Force Authn + type: boolean + examples: + - true + idp_certificates: + description: IDP Certificates + type: array + items: + type: object + $ref: ./connectionsIDPCertificate.yaml + idp_entity_id: + description: IDP Entity ID + type: string + examples: + - https://youridp.com/service/saml + idp_metadata_url: + description: IDP Metadata URL + type: string + examples: + - https://youridp.com/service/saml/metadata + idp_name_id_format: + description: IDP Name ID Format + $ref: ./connectionsNameIdFormat.yaml + examples: + - EMAIL + idp_slo_request_binding: + description: IDP SLO Request Binding + $ref: ./connectionsRequestBinding.yaml + examples: + - HTTP_POST + idp_slo_required: + description: Enable IDP logout + type: boolean + examples: + - true + idp_slo_url: + description: IDP SLO URL + type: string + examples: + - https://youridp.com/service/saml/slo + idp_sso_request_binding: + description: IDP SSO Request Binding + $ref: ./connectionsRequestBinding.yaml + examples: + - HTTP_POST + idp_sso_url: + description: IDP SSO URL + type: string + examples: + - https://youridp.com/service/saml/sso + jit_provisioning_with_sso_enabled: + description: Indicates if Just In Time user provisioning is enabled for the connection + type: boolean + examples: + - true + saml_signing_option: + description: SAML Signing Option + $ref: ./connectionsSAMLSigningOptions.yaml + examples: + - SAML_ONLY_RESPONSE_SIGNING + sp_assertion_url: + description: SP Assertion URL + type: string + examples: + - https://youridp.com/service/saml/assertion + sp_entity_id: + description: SP Entity ID + type: string + examples: + - https://yourapp.com/service/saml + sp_metadata_url: + description: SP Metadata URL + type: string + examples: + - https://youridp.com/service/saml/metadata + sp_slo_url: + description: Service Provider SLO url + type: string + readOnly: true + examples: + - https://yourapp.com/sso/v1/saml/conn_1234/slo/callback + sync_user_profile_on_login: + description: >- + Indicates whether user profiles should be synchronized with the identity + provider upon each log-in. + type: boolean + examples: + - true + ui_button_title: + description: UI Button Title + type: string + examples: + - Login with SSO + want_request_signed: + description: Want Request Signed + type: boolean + examples: + - true diff --git a/openapi/components/schemas/connectionsSAMLSigningOptions.yaml b/openapi/components/schemas/connectionsSAMLSigningOptions.yaml new file mode 100644 index 000000000..df65f1e2e --- /dev/null +++ b/openapi/components/schemas/connectionsSAMLSigningOptions.yaml @@ -0,0 +1,8 @@ +type: string +title: enums all +enum: + - NO_SIGNING + - SAML_ONLY_RESPONSE_SIGNING + - SAML_ONLY_ASSERTION_SIGNING + - SAML_RESPONSE_ASSERTION_SIGNING + - SAML_RESPONSE_OR_ASSERTION_SIGNING diff --git a/openapi/components/schemas/connectionsStaticAuthConfig.yaml b/openapi/components/schemas/connectionsStaticAuthConfig.yaml new file mode 100644 index 000000000..6b92c29f7 --- /dev/null +++ b/openapi/components/schemas/connectionsStaticAuthConfig.yaml @@ -0,0 +1,4 @@ +type: object +properties: + static_config: + type: object diff --git a/openapi/components/schemas/connectionsToggleConnectionResponse.yaml b/openapi/components/schemas/connectionsToggleConnectionResponse.yaml new file mode 100644 index 000000000..1c5a3439c --- /dev/null +++ b/openapi/components/schemas/connectionsToggleConnectionResponse.yaml @@ -0,0 +1,14 @@ +type: object +properties: + enabled: + description: >- + Current state of the connection after the operation. True means the + connection is now enabled and can be used for authentication. + type: boolean + examples: + - true + error_message: + description: Error message if the operation fails + type: string + examples: + - placeholder diff --git a/openapi/components/schemas/connectionsTokenAuthType.yaml b/openapi/components/schemas/connectionsTokenAuthType.yaml new file mode 100644 index 000000000..2d86a6827 --- /dev/null +++ b/openapi/components/schemas/connectionsTokenAuthType.yaml @@ -0,0 +1,4 @@ +type: string +enum: + - URL_PARAMS + - BASIC_AUTH diff --git a/openapi/components/schemas/connectionsWebAuthConfiguration.yaml b/openapi/components/schemas/connectionsWebAuthConfiguration.yaml new file mode 100644 index 000000000..5d3346615 --- /dev/null +++ b/openapi/components/schemas/connectionsWebAuthConfiguration.yaml @@ -0,0 +1,24 @@ +type: object +title: >- + WebAuthConfiguration defines WebAuthn (passkeys) configuration limited to RP + and Attestation +properties: + attestation: + $ref: ./WebAuthConfigurationAttestation.yaml + authenticator_selection: + $ref: ./WebAuthConfigurationAuthenticatorSelection.yaml + authenticators: + $ref: ./WebAuthConfigurationAuthenticators.yaml + enable_auto_registration: + description: Enable auto registration for WebAuthn + type: boolean + enable_conditional_login: + description: Allow autofill of passkeys in login page + type: boolean + rp: + $ref: ./WebAuthConfigurationRp.yaml + show_passkey_button: + description: Show passkey button on login screen + type: boolean + timeout: + $ref: ./WebAuthConfigurationTimeout.yaml diff --git a/openapi/components/schemas/directoriesAttributeMapping.yaml b/openapi/components/schemas/directoriesAttributeMapping.yaml new file mode 100644 index 000000000..af01ab018 --- /dev/null +++ b/openapi/components/schemas/directoriesAttributeMapping.yaml @@ -0,0 +1,6 @@ +type: object +properties: + key: + type: string + map_to: + type: string diff --git a/openapi/components/schemas/directoriesAttributeMappings.yaml b/openapi/components/schemas/directoriesAttributeMappings.yaml new file mode 100644 index 000000000..75e5932cd --- /dev/null +++ b/openapi/components/schemas/directoriesAttributeMappings.yaml @@ -0,0 +1,7 @@ +type: object +properties: + attributes: + type: array + items: + type: object + $ref: ./directoriesAttributeMapping.yaml diff --git a/openapi/components/schemas/directoriesDirectory.yaml b/openapi/components/schemas/directoriesDirectory.yaml new file mode 100644 index 000000000..ac0c14674 --- /dev/null +++ b/openapi/components/schemas/directoriesDirectory.yaml @@ -0,0 +1,103 @@ +type: object +properties: + attribute_mappings: + description: >- + Mappings between directory attributes and Scalekit user and group + attributes + $ref: ./directoriesAttributeMappings.yaml + directory_endpoint: + description: >- + The endpoint URL generated by Scalekit for synchronizing users and groups + from the Directory Provider + type: string + examples: + - https://yourapp.scalekit.com/api/v1/directoies/dir_123212312/scim/v2 + directory_provider: + description: Identity provider connected to this directory + $ref: ./directoriesDirectoryProvider.yaml + examples: + - OKTA + directory_type: + description: >- + Type of the directory, indicating the protocol or standard used for + synchronization + $ref: ./directoriesDirectoryType.yaml + examples: + - SCIM + email: + description: Email Id associated with Directory whose access will be used for polling + type: string + examples: + - john.doe@scalekit.cloud + enabled: + description: >- + Indicates whether the directory is currently enabled and actively + synchronizing users and groups + type: boolean + examples: + - true + groups_tracked: + description: It indicates if all groups are tracked or select groups are tracked + type: string + examples: + - ALL + id: + description: Unique identifier of the directory + type: string + examples: + - dir_121312434123312 + last_synced_at: + description: >- + Timestamp of the last successful synchronization of users and groups from + the Directory Provider + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + name: + description: >- + Name of the directory, typically representing the connected Directory + provider + type: string + examples: + - Azure AD + organization_id: + description: Unique identifier of the organization to which the directory belongs + type: string + examples: + - org_121312434123312 + role_assignments: + description: >- + Role assignments associated with the directory, defining group based role + assignments + $ref: ./directoriesRoleAssignments.yaml + secrets: + description: >- + List of secrets used for authenticating and synchronizing with the + Directory Provider + type: array + items: + type: object + $ref: ./directoriesSecret.yaml + stats: + description: >- + Statistics and metrics related to the directory, such as synchronization + status and error counts + $ref: ./directoriesStats.yaml + status: + description: Directory Status + type: string + examples: + - IN_PROGRESS + total_groups: + description: Total number of groups in the directory + type: integer + format: int32 + examples: + - 10 + total_users: + description: Total number of users in the directory + type: integer + format: int32 + examples: + - 10 diff --git a/openapi/components/schemas/directoriesDirectoryGroup.yaml b/openapi/components/schemas/directoriesDirectoryGroup.yaml new file mode 100644 index 000000000..687a2b52b --- /dev/null +++ b/openapi/components/schemas/directoriesDirectoryGroup.yaml @@ -0,0 +1,27 @@ +type: object +properties: + display_name: + description: Display Name + type: string + examples: + - Admins + group_detail: + description: Complete Group Details Payload + type: object + id: + description: Group ID + type: string + examples: + - dirgroup_121312434123312 + total_users: + description: Total Users in the Group + type: integer + format: int32 + examples: + - 10 + updated_at: + description: Updated At + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' diff --git a/openapi/components/schemas/directoriesDirectoryProvider.yaml b/openapi/components/schemas/directoriesDirectoryProvider.yaml new file mode 100644 index 000000000..5681a39dc --- /dev/null +++ b/openapi/components/schemas/directoriesDirectoryProvider.yaml @@ -0,0 +1,9 @@ +type: string +enum: + - OKTA + - GOOGLE + - MICROSOFT_AD + - AUTH0 + - ONELOGIN + - JUMPCLOUD + - PING_IDENTITY diff --git a/openapi/components/schemas/directoriesDirectoryType.yaml b/openapi/components/schemas/directoriesDirectoryType.yaml new file mode 100644 index 000000000..fa5e0634b --- /dev/null +++ b/openapi/components/schemas/directoriesDirectoryType.yaml @@ -0,0 +1,5 @@ +type: string +enum: + - SCIM + - LDAP + - POLL diff --git a/openapi/components/schemas/directoriesDirectoryUser.yaml b/openapi/components/schemas/directoriesDirectoryUser.yaml new file mode 100644 index 000000000..a0784ce5a --- /dev/null +++ b/openapi/components/schemas/directoriesDirectoryUser.yaml @@ -0,0 +1,47 @@ +type: object +properties: + email: + description: Email + type: string + examples: + - johndoe + emails: + description: Emails + type: array + items: + type: string + family_name: + description: Last Name + type: string + examples: + - Doe + given_name: + description: First Name + type: string + examples: + - John + groups: + description: Groups + type: array + items: + type: object + $ref: ./directoriesDirectoryGroup.yaml + id: + description: User ID + type: string + examples: + - diruser_121312434123312 + preferred_username: + description: Preferred Username + type: string + examples: + - johndoe + updated_at: + description: Updated At + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + user_detail: + description: Complete User Details Payload + type: object diff --git a/openapi/components/schemas/directoriesGetDirectoryResponse.yaml b/openapi/components/schemas/directoriesGetDirectoryResponse.yaml new file mode 100644 index 000000000..7aab956a0 --- /dev/null +++ b/openapi/components/schemas/directoriesGetDirectoryResponse.yaml @@ -0,0 +1,5 @@ +type: object +properties: + directory: + description: Detailed information about the requested directory + $ref: ./directoriesDirectory.yaml diff --git a/openapi/components/schemas/directoriesListDirectoriesResponse.yaml b/openapi/components/schemas/directoriesListDirectoriesResponse.yaml new file mode 100644 index 000000000..cec72e21e --- /dev/null +++ b/openapi/components/schemas/directoriesListDirectoriesResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + directories: + description: List of directories associated with the organization + type: array + items: + type: object + $ref: ./directoriesDirectory.yaml diff --git a/openapi/components/schemas/directoriesListDirectoryGroupsResponse.yaml b/openapi/components/schemas/directoriesListDirectoryGroupsResponse.yaml new file mode 100644 index 000000000..8d5e1266a --- /dev/null +++ b/openapi/components/schemas/directoriesListDirectoryGroupsResponse.yaml @@ -0,0 +1,24 @@ +type: object +properties: + groups: + description: List of directory groups retrieved from the specified directory + type: array + items: + type: object + $ref: ./directoriesDirectoryGroup.yaml + next_page_token: + description: >- + Token to retrieve the next page of results. Use this token in the + 'page_token' field of the next request + type: string + prev_page_token: + description: >- + Token to retrieve the previous page of results. Use this token in the + 'page_token' field of the next request + type: string + total_size: + description: >- + Total number of groups matching the request criteria, regardless of + pagination + type: integer + format: int64 diff --git a/openapi/components/schemas/directoriesListDirectoryUsersResponse.yaml b/openapi/components/schemas/directoriesListDirectoryUsersResponse.yaml new file mode 100644 index 000000000..8c5efab96 --- /dev/null +++ b/openapi/components/schemas/directoriesListDirectoryUsersResponse.yaml @@ -0,0 +1,24 @@ +type: object +properties: + next_page_token: + description: >- + Token for pagination. Use this token in the 'page_token' field of the next + request to fetch the subsequent page of users + type: string + prev_page_token: + description: >- + Token for pagination. Use this token in the 'page_token' field of the next + request to fetch the prior page of users + type: string + total_size: + description: >- + Total number of users available in the directory that match the request + criteria + type: integer + format: int64 + users: + description: List of directory users retrieved from the specified directory + type: array + items: + type: object + $ref: ./directoriesDirectoryUser.yaml diff --git a/openapi/components/schemas/directoriesRoleAssignment.yaml b/openapi/components/schemas/directoriesRoleAssignment.yaml new file mode 100644 index 000000000..79400b474 --- /dev/null +++ b/openapi/components/schemas/directoriesRoleAssignment.yaml @@ -0,0 +1,9 @@ +type: object +properties: + group_id: + description: group ID for the role mapping + type: string + examples: + - dirgroup_121312434123 + role_name: + type: string diff --git a/openapi/components/schemas/directoriesRoleAssignments.yaml b/openapi/components/schemas/directoriesRoleAssignments.yaml new file mode 100644 index 000000000..94af41d65 --- /dev/null +++ b/openapi/components/schemas/directoriesRoleAssignments.yaml @@ -0,0 +1,7 @@ +type: object +properties: + assignments: + type: array + items: + type: object + $ref: ./directoriesRoleAssignment.yaml diff --git a/openapi/components/schemas/directoriesSecret.yaml b/openapi/components/schemas/directoriesSecret.yaml new file mode 100644 index 000000000..a35aab6ac --- /dev/null +++ b/openapi/components/schemas/directoriesSecret.yaml @@ -0,0 +1,37 @@ +type: object +properties: + create_time: + description: Creation Time + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + directory_id: + description: Directory ID + type: string + examples: + - dir_12362474900684814 + expire_time: + description: Expiry Time + type: string + format: date-time + examples: + - '2025-10-01T00:00:00Z' + id: + type: string + last_used_time: + description: Last Used Time + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + secret_suffix: + description: Secret Suffix + type: string + examples: + - Nzg5 + status: + description: Secret Status + $ref: ./directoriesSecretStatus.yaml + examples: + - INACTIVE diff --git a/openapi/components/schemas/directoriesSecretStatus.yaml b/openapi/components/schemas/directoriesSecretStatus.yaml new file mode 100644 index 000000000..70679d3b0 --- /dev/null +++ b/openapi/components/schemas/directoriesSecretStatus.yaml @@ -0,0 +1,3 @@ +type: string +enum: + - INACTIVE diff --git a/openapi/components/schemas/directoriesStats.yaml b/openapi/components/schemas/directoriesStats.yaml new file mode 100644 index 000000000..14fb24211 --- /dev/null +++ b/openapi/components/schemas/directoriesStats.yaml @@ -0,0 +1,26 @@ +type: object +properties: + group_updated_at: + description: Max time of Group Updated At for Directory + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + total_groups: + description: Total Groups in the Directory + type: integer + format: int32 + examples: + - 10 + total_users: + description: Total Users in the Directory + type: integer + format: int32 + examples: + - 10 + user_updated_at: + description: Max time of User Updated At for Directory + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' diff --git a/openapi/components/schemas/directoriesToggleDirectoryResponse.yaml b/openapi/components/schemas/directoriesToggleDirectoryResponse.yaml new file mode 100644 index 000000000..d4ecac396 --- /dev/null +++ b/openapi/components/schemas/directoriesToggleDirectoryResponse.yaml @@ -0,0 +1,19 @@ +type: object +properties: + enabled: + description: >- + Specifies the directory's state after the toggle operation. A value of + `true` indicates that the directory is enabled and actively synchronizing + users and groups. A value of `false` means the directory is disabled, + halting synchronization + type: boolean + examples: + - true + error_message: + description: >- + Contains a human-readable error message if the toggle operation + encountered an issue. If the operation was successful, this field will be + empty + type: string + examples: + - The directory is already enabled diff --git a/openapi/components/schemas/domainsCreateDomainResponse.yaml b/openapi/components/schemas/domainsCreateDomainResponse.yaml new file mode 100644 index 000000000..0e29e0d29 --- /dev/null +++ b/openapi/components/schemas/domainsCreateDomainResponse.yaml @@ -0,0 +1,7 @@ +type: object +properties: + domain: + description: >- + The newly created domain object with all configuration details and + system-generated identifiers. + $ref: ./domainsDomain.yaml diff --git a/openapi/components/schemas/domainsDomain.yaml b/openapi/components/schemas/domainsDomain.yaml new file mode 100644 index 000000000..87cd699e7 --- /dev/null +++ b/openapi/components/schemas/domainsDomain.yaml @@ -0,0 +1,67 @@ +type: object +properties: + create_time: + description: Timestamp when the domain was first created. + type: string + format: date-time + examples: + - '2025-09-01T12:14:43.100000Z' + domain: + description: >- + The business domain name that was configured for allowed email domain + functionality (e.g., company.com, subdomain.company.com). + type: string + examples: + - customerdomain.com + domain_type: + example: ORGANIZATION_DOMAIN + environment_id: + description: The environment ID where this domain is configured. + type: string + examples: + - env_58345499215790610 + id: + description: Scalekit-generated unique identifier for this domain record. + type: string + examples: + - dom_88351643129225005 + organization_id: + description: The organization to which the domain belongs. + type: string + examples: + - org_81667076086825451 + update_time: + description: Timestamp when the domain was last updated. + type: string + format: date-time + examples: + - '2025-09-01T12:14:43.110455Z' + verification_method: + description: >- + Method that determines how domain ownership is verified. + + - ADMIN: domain is marked verified without DNS validation, typically by an + admin. + + - DNS: domain must be verified by adding a TXT record to your DNS + configuration. + + - NOT_APPLICABLE: verification does not apply to this domain type. + $ref: ./domainsVerificationMethod.yaml + examples: + - ADMIN + verification_status: + description: >- + Verification status of the domain. + + - PENDING: DNS TXT record has not been validated yet. + + - VERIFIED: domain confirmed via DNS TXT record validation or admin + approval. + + - AUTO_VERIFIED: domain verified automatically without DNS changes. + + - FAILED: DNS TXT record was not validated within the verification window. + $ref: ./domainsVerificationStatus.yaml + examples: + - AUTO_VERIFIED diff --git a/openapi/components/schemas/domainsDomainType.yaml b/openapi/components/schemas/domainsDomainType.yaml new file mode 100644 index 000000000..4ec302d67 --- /dev/null +++ b/openapi/components/schemas/domainsDomainType.yaml @@ -0,0 +1,7 @@ +type: string +enum: + - ALLOWED_EMAIL_DOMAIN + - ORGANIZATION_DOMAIN +x-enum-varnames: + - ORGANIZATION_DOMAIN + - ALLOWED_EMAIL_DOMAIN diff --git a/openapi/components/schemas/domainsGetDomainResponse.yaml b/openapi/components/schemas/domainsGetDomainResponse.yaml new file mode 100644 index 000000000..34f90a034 --- /dev/null +++ b/openapi/components/schemas/domainsGetDomainResponse.yaml @@ -0,0 +1,7 @@ +type: object +properties: + domain: + description: >- + The requested domain object with complete details including domain type, + timestamps and configuration. + $ref: ./domainsDomain.yaml diff --git a/openapi/components/schemas/domainsListDomainResponse.yaml b/openapi/components/schemas/domainsListDomainResponse.yaml new file mode 100644 index 000000000..be1d72b65 --- /dev/null +++ b/openapi/components/schemas/domainsListDomainResponse.yaml @@ -0,0 +1,22 @@ +type: object +properties: + domains: + description: >- + Array of domain objects containing all domain details including + verification status and configuration. + type: array + items: + type: object + $ref: ./domainsDomain.yaml + page_number: + description: Current page number in the pagination sequence. + type: integer + format: int32 + examples: + - 1 + page_size: + description: Number of domains returned in this page. + type: integer + format: int32 + examples: + - 1 diff --git a/openapi/components/schemas/domainsVerificationMethod.yaml b/openapi/components/schemas/domainsVerificationMethod.yaml new file mode 100644 index 000000000..807f462dd --- /dev/null +++ b/openapi/components/schemas/domainsVerificationMethod.yaml @@ -0,0 +1,5 @@ +type: string +enum: + - ADMIN + - DNS + - NOT_APPLICABLE diff --git a/openapi/components/schemas/domainsVerificationStatus.yaml b/openapi/components/schemas/domainsVerificationStatus.yaml new file mode 100644 index 000000000..308b57497 --- /dev/null +++ b/openapi/components/schemas/domainsVerificationStatus.yaml @@ -0,0 +1,6 @@ +type: string +enum: + - PENDING + - VERIFIED + - FAILED + - AUTO_VERIFIED diff --git a/openapi/components/schemas/errdetailsDebugInfo.yaml b/openapi/components/schemas/errdetailsDebugInfo.yaml new file mode 100644 index 000000000..5b457fa8d --- /dev/null +++ b/openapi/components/schemas/errdetailsDebugInfo.yaml @@ -0,0 +1,11 @@ +description: Describes additional debugging info. +type: object +properties: + detail: + description: Additional debugging information provided by the server. + type: string + stack_entries: + description: The stack trace entries indicating where the error occurred. + type: array + items: + type: string diff --git a/openapi/components/schemas/errdetailsErrorInfo.yaml b/openapi/components/schemas/errdetailsErrorInfo.yaml new file mode 100644 index 000000000..21fa4d3a9 --- /dev/null +++ b/openapi/components/schemas/errdetailsErrorInfo.yaml @@ -0,0 +1,18 @@ +type: object +properties: + debug_info: + $ref: ./errdetailsDebugInfo.yaml + error_code: + type: string + help_info: + $ref: ./errdetailsHelpInfo.yaml + localized_message_info: + $ref: ./errdetailsLocalizedMessageInfo.yaml + request_info: + $ref: ./errdetailsRequestInfo.yaml + resource_info: + $ref: ./errdetailsResourceInfo.yaml + tool_error_info: + $ref: ./errdetailsToolErrorInfo.yaml + validation_error_info: + $ref: ./errdetailsValidationErrorInfo.yaml diff --git a/openapi/components/schemas/errdetailsHelpInfo.yaml b/openapi/components/schemas/errdetailsHelpInfo.yaml new file mode 100644 index 000000000..c96cdb3c9 --- /dev/null +++ b/openapi/components/schemas/errdetailsHelpInfo.yaml @@ -0,0 +1,13 @@ +description: |- + HelpInfo provides documentation links attached to an error response. + When present in ErrorInfo, clients should surface these links to help + developers resolve the error. For example, a missing required field error + may include a link to the relevant guide. +type: object +properties: + links: + description: One or more links relevant to resolving the error. + type: array + items: + type: object + $ref: ./HelpInfoLink.yaml diff --git a/openapi/components/schemas/errdetailsLocalizedMessageInfo.yaml b/openapi/components/schemas/errdetailsLocalizedMessageInfo.yaml new file mode 100644 index 000000000..e8682167b --- /dev/null +++ b/openapi/components/schemas/errdetailsLocalizedMessageInfo.yaml @@ -0,0 +1,6 @@ +type: object +properties: + locale: + type: string + message: + type: string diff --git a/openapi/components/schemas/errdetailsRequestInfo.yaml b/openapi/components/schemas/errdetailsRequestInfo.yaml new file mode 100644 index 000000000..bdd6fac5a --- /dev/null +++ b/openapi/components/schemas/errdetailsRequestInfo.yaml @@ -0,0 +1,17 @@ +description: |- + Contains metadata about the request that clients can attach when filing a bug + or providing other forms of feedback. +type: object +properties: + request_id: + description: >- + An opaque string that should only be interpreted by the service generating + + it. For example, it can be used to identify requests in the service's + logs. + type: string + serving_data: + description: |- + Any data that was used to serve this request. For example, an encrypted + stack trace that can be sent back to the service provider for debugging. + type: string diff --git a/openapi/components/schemas/errdetailsResourceInfo.yaml b/openapi/components/schemas/errdetailsResourceInfo.yaml new file mode 100644 index 000000000..ffa4af94f --- /dev/null +++ b/openapi/components/schemas/errdetailsResourceInfo.yaml @@ -0,0 +1,20 @@ +description: Describes the resource that is being accessed. +type: object +properties: + description: + description: |- + Describes what error is encountered when accessing this resource. + For example, updating a cloud project may require the `writer` permission + on the developer console project. + type: string + owner: + type: string + required_permissions: + description: The required permissions needed to access the resource. + type: array + items: + type: string + resource_name: + type: string + user: + type: string diff --git a/openapi/components/schemas/errdetailsToolErrorInfo.yaml b/openapi/components/schemas/errdetailsToolErrorInfo.yaml new file mode 100644 index 000000000..7ed62c888 --- /dev/null +++ b/openapi/components/schemas/errdetailsToolErrorInfo.yaml @@ -0,0 +1,8 @@ +type: object +properties: + execution_id: + type: string + tool_error_code: + type: string + tool_error_message: + type: string diff --git a/openapi/components/schemas/errdetailsValidationErrorInfo.yaml b/openapi/components/schemas/errdetailsValidationErrorInfo.yaml new file mode 100644 index 000000000..e2f50ca2c --- /dev/null +++ b/openapi/components/schemas/errdetailsValidationErrorInfo.yaml @@ -0,0 +1,11 @@ +description: |- + Describes violations in a client request. This error type focuses on the + syntactic aspects of the request. +type: object +properties: + field_violations: + description: Describes all violations in a client request. + type: array + items: + type: object + $ref: ./ValidationErrorInfoFieldViolation.yaml diff --git a/openapi/components/schemas/organizationsCreateOrganizationResponse.yaml b/openapi/components/schemas/organizationsCreateOrganizationResponse.yaml new file mode 100644 index 000000000..89a6d5864 --- /dev/null +++ b/openapi/components/schemas/organizationsCreateOrganizationResponse.yaml @@ -0,0 +1,5 @@ +type: object +properties: + organization: + description: The newly created organization containing its ID, settings, and metadata + $ref: ./organizationsOrganization.yaml diff --git a/openapi/components/schemas/organizationsFeature.yaml b/openapi/components/schemas/organizationsFeature.yaml new file mode 100644 index 000000000..3fef4daa8 --- /dev/null +++ b/openapi/components/schemas/organizationsFeature.yaml @@ -0,0 +1,10 @@ +description: |- + - dir_sync: Enables directory synchronization configuration in the portal + - sso: Enables Single Sign-On (SSO) configuration in the portal +type: string +title: >- + Feature represents the available features that can be enabled for an + organization's portal link +enum: + - dir_sync + - sso diff --git a/openapi/components/schemas/organizationsGeneratePortalLinkResponse.yaml b/openapi/components/schemas/organizationsGeneratePortalLinkResponse.yaml new file mode 100644 index 000000000..bfc09d41f --- /dev/null +++ b/openapi/components/schemas/organizationsGeneratePortalLinkResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + link: + description: >- + Contains the generated admin portal link details. The link URL can be + shared with organization administrators to set up: Single Sign-On (SSO) + authentication and directory synchronization + $ref: ./organizationsLink.yaml diff --git a/openapi/components/schemas/organizationsGetOrganizationResponse.yaml b/openapi/components/schemas/organizationsGetOrganizationResponse.yaml new file mode 100644 index 000000000..716b7b28c --- /dev/null +++ b/openapi/components/schemas/organizationsGetOrganizationResponse.yaml @@ -0,0 +1,5 @@ +type: object +properties: + organization: + description: The newly created organization + $ref: ./organizationsOrganization.yaml diff --git a/openapi/components/schemas/organizationsGetOrganizationSessionPolicyResponse.yaml b/openapi/components/schemas/organizationsGetOrganizationSessionPolicyResponse.yaml new file mode 100644 index 000000000..51c07a047 --- /dev/null +++ b/openapi/components/schemas/organizationsGetOrganizationSessionPolicyResponse.yaml @@ -0,0 +1,5 @@ +type: object +properties: + policy: + description: The session policy for the organization. + $ref: ./organizationsOrganizationSessionPolicySettings.yaml diff --git a/openapi/components/schemas/organizationsLink.yaml b/openapi/components/schemas/organizationsLink.yaml new file mode 100644 index 000000000..40b068ab6 --- /dev/null +++ b/openapi/components/schemas/organizationsLink.yaml @@ -0,0 +1,20 @@ +type: object +properties: + expire_time: + description: Expiry time of the link. The link is valid for 1 minute. + type: string + format: date-time + examples: + - '2024-02-06T14:48:00Z' + id: + description: Unique Identifier for the link + type: string + examples: + - lnk_123123123123123 + location: + description: >- + Location of the link. This is the URL that can be used to access the Admin + portal. The link is valid for 1 minute + type: string + examples: + - https://scalekit.com/portal/lnk_123123123123123 diff --git a/openapi/components/schemas/organizationsListOrganizationsResponse.yaml b/openapi/components/schemas/organizationsListOrganizationsResponse.yaml new file mode 100644 index 000000000..dffb4b426 --- /dev/null +++ b/openapi/components/schemas/organizationsListOrganizationsResponse.yaml @@ -0,0 +1,28 @@ +type: object +properties: + next_page_token: + description: >- + Pagination token for the next page of results. Use this token to fetch the + next page. + type: string + examples: + - + organizations: + description: List of organization objects + type: array + items: + type: object + $ref: ./organizationsOrganization.yaml + prev_page_token: + description: >- + Pagination token for the previous page of results. Use this token to fetch + the previous page. + type: string + examples: + - + total_size: + description: Total number of organizations in the environment. + type: integer + format: int64 + examples: + - 30 diff --git a/openapi/components/schemas/organizationsOrganization.yaml b/openapi/components/schemas/organizationsOrganization.yaml new file mode 100644 index 000000000..a4b85a67c --- /dev/null +++ b/openapi/components/schemas/organizationsOrganization.yaml @@ -0,0 +1,77 @@ +type: object +required: + - create_time +properties: + create_time: + description: Timestamp when the organization was created + type: string + format: date-time + title: Created Time + examples: + - '2025-02-15T06:23:44.560000Z' + display_name: + description: Name of the organization. Must be between 1 and 200 characters + type: string + title: Name of the org to be used in display + examples: + - Megasoft + external_id: + description: >- + Your application's unique identifier for this organization, used to link + Scalekit with your system. + type: string + title: >- + External Id is useful to store a unique identifier for a given Org that. + The unique Identifier can be the id of your tenant / org in your SaaSApp + examples: + - my_unique_id + id: + description: >- + Unique scalekit-generated identifier that uniquely references an + organization + type: string + title: Id + examples: + - org_59615193906282635 + logo_url: + description: >- + HTTPS URL of the organization's logo image. Maximum 2048 characters. Must + use the https scheme. + type: string + format: uri + maxLength: 2048 + pattern: ^https:// + examples: + - https://cdn.example.com/acme-logo.png + metadata: + description: Key value pairs extension attributes. + type: object + additionalProperties: + type: string + region_code: + description: Geographic region code for the organization. Currently limited to US. + title: Optional regioncode + $ref: ./commonsRegionCode.yaml + examples: + - US + settings: + title: Organization Settings + $ref: ./organizationsOrganizationSettings.yaml + slug: + description: >- + DNS-safe slug for dynamic redirect URI resolution. Must be 1-63 chars, + lowercase alphanumeric and hyphens, must start and end with an + alphanumeric character. Unique per environment. + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([a-z0-9]|-[a-z0-9])*$ + examples: + - acme + update_time: + description: Timestamp when the organization was last updated + type: string + format: date-time + title: Updated time + examples: + - '2025-02-15T06:23:44.560000Z' diff --git a/openapi/components/schemas/organizationsOrganizationSessionPolicySettings.yaml b/openapi/components/schemas/organizationsOrganizationSessionPolicySettings.yaml new file mode 100644 index 000000000..48489b26b --- /dev/null +++ b/openapi/components/schemas/organizationsOrganizationSessionPolicySettings.yaml @@ -0,0 +1,49 @@ +type: object +properties: + absolute_session_timeout: + description: >- + The absolute session timeout value. The unit is specified by + absolute_session_timeout_unit. Omitted when policy_source is + 'environment'. + type: integer + format: int32 + examples: + - 360 + absolute_session_timeout_unit: + description: >- + Unit for absolute_session_timeout. Accepted values: 'minutes', 'hours', + 'days'. Responses always return 'minutes'. + $ref: ./commonsTimeUnit.yaml + examples: + - minutes + idle_session_timeout: + description: >- + The idle session timeout value. The unit is specified by + idle_session_timeout_unit. Omitted when idle_session_timeout_enabled is + false or policy_source is 'environment'. + type: integer + format: int32 + examples: + - 84 + idle_session_timeout_enabled: + description: >- + Whether idle session timeout is enabled for this organization. Omitted + when policy_source is 'environment'. + type: boolean + examples: + - true + idle_session_timeout_unit: + description: >- + Unit for idle_session_timeout. Accepted values: 'minutes', 'hours', + 'days'. Responses always return 'minutes'. + $ref: ./commonsTimeUnit.yaml + examples: + - minutes + policy_source: + description: >- + Policy source. 'APPLICATION' means the organization inherits the + application-level session policy. 'CUSTOM' means organization-specific + timeout values are active. + $ref: ./organizationsSessionPolicyType.yaml + examples: + - CUSTOM diff --git a/openapi/components/schemas/organizationsOrganizationSettings.yaml b/openapi/components/schemas/organizationsOrganizationSettings.yaml new file mode 100644 index 000000000..3f654d798 --- /dev/null +++ b/openapi/components/schemas/organizationsOrganizationSettings.yaml @@ -0,0 +1,25 @@ +description: >- + Configuration options that control organization-level features and + capabilities +type: object +title: Organization Settings +properties: + features: + description: >- + List of feature toggles that control organization capabilities such as SSO + authentication and directory synchronization + type: array + items: + type: object + $ref: ./organizationsOrganizationSettingsFeature.yaml + examples: + - - enabled: true + name: sso + - enabled: false + name: directory_sync +examples: + - features: + - enabled: true + name: sso + - enabled: false + name: directory_sync diff --git a/openapi/components/schemas/organizationsOrganizationSettingsFeature.yaml b/openapi/components/schemas/organizationsOrganizationSettingsFeature.yaml new file mode 100644 index 000000000..15a9d41f4 --- /dev/null +++ b/openapi/components/schemas/organizationsOrganizationSettingsFeature.yaml @@ -0,0 +1,23 @@ +description: Controls the activation state of a specific organization feature +type: object +title: Organization Feature Toggle +required: + - name + - enabled +properties: + enabled: + description: >- + Whether the feature is enabled (true) or disabled (false) for this + organization + type: boolean + examples: + - true + name: + description: >- + Feature identifier. Supported values include: "sso" (Single Sign-On), + "directory_sync" (Directory Synchronization), "domain_verification" + (Domain Verification), "session_policy" (Organization-level session policy + override) + type: string + examples: + - sso diff --git a/openapi/components/schemas/organizationsOrganizationUserManagementSettings.yaml b/openapi/components/schemas/organizationsOrganizationUserManagementSettings.yaml new file mode 100644 index 000000000..9cb4326f9 --- /dev/null +++ b/openapi/components/schemas/organizationsOrganizationUserManagementSettings.yaml @@ -0,0 +1,12 @@ +type: object +properties: + max_allowed_users: + description: >- + Maximum number of users allowed in the organization. When nil (not set), + there feature is not enabled. When explicitly set to zero, it also means + no limit. When set to a positive integer, it enforces the maximum user + limit. + type: integer + format: int32 + examples: + - 100 diff --git a/openapi/components/schemas/organizationsSessionPolicyType.yaml b/openapi/components/schemas/organizationsSessionPolicyType.yaml new file mode 100644 index 000000000..3acf10c72 --- /dev/null +++ b/openapi/components/schemas/organizationsSessionPolicyType.yaml @@ -0,0 +1,4 @@ +type: string +enum: + - APPLICATION + - CUSTOM diff --git a/openapi/components/schemas/organizationsUpdateOrganizationResponse.yaml b/openapi/components/schemas/organizationsUpdateOrganizationResponse.yaml new file mode 100644 index 000000000..654a97897 --- /dev/null +++ b/openapi/components/schemas/organizationsUpdateOrganizationResponse.yaml @@ -0,0 +1,5 @@ +type: object +properties: + organization: + description: Updated organization details + $ref: ./organizationsOrganization.yaml diff --git a/openapi/components/schemas/organizationsUpdateOrganizationSessionPolicyResponse.yaml b/openapi/components/schemas/organizationsUpdateOrganizationSessionPolicyResponse.yaml new file mode 100644 index 000000000..451a0a393 --- /dev/null +++ b/openapi/components/schemas/organizationsUpdateOrganizationSessionPolicyResponse.yaml @@ -0,0 +1,5 @@ +type: object +properties: + policy: + description: The updated session policy for the organization. + $ref: ./organizationsOrganizationSessionPolicySettings.yaml diff --git a/openapi/components/schemas/organizationsUpsertUserManagementSettingsResponse.yaml b/openapi/components/schemas/organizationsUpsertUserManagementSettingsResponse.yaml new file mode 100644 index 000000000..13b1cb0ef --- /dev/null +++ b/openapi/components/schemas/organizationsUpsertUserManagementSettingsResponse.yaml @@ -0,0 +1,5 @@ +type: object +properties: + settings: + description: The updated setting. + $ref: ./organizationsOrganizationUserManagementSettings.yaml diff --git a/openapi/components/schemas/passwordlessResendPasswordlessRequest.yaml b/openapi/components/schemas/passwordlessResendPasswordlessRequest.yaml new file mode 100644 index 000000000..0e8ba2aab --- /dev/null +++ b/openapi/components/schemas/passwordlessResendPasswordlessRequest.yaml @@ -0,0 +1,10 @@ +type: object +properties: + auth_request_id: + description: >- + The authentication request identifier from the original send passwordless + email request. Use this to resend the Verification Code (OTP) or Magic + Link to the same email address. + type: string + examples: + - h5Y8kT5RVwaea5WEgW4n-6C-aO_-fuTUW7Vb9-Rh3AcY9qxZqQ diff --git a/openapi/components/schemas/passwordlessSendPasswordlessRequest.yaml b/openapi/components/schemas/passwordlessSendPasswordlessRequest.yaml new file mode 100644 index 000000000..1b71feb2d --- /dev/null +++ b/openapi/components/schemas/passwordlessSendPasswordlessRequest.yaml @@ -0,0 +1,65 @@ +type: object +properties: + email: + description: >- + Email address where the passwordless authentication credentials will be + sent. Must be a valid email format. + type: string + examples: + - john.doe@example.com + expires_in: + description: >- + Time in seconds until the passwordless authentication expires. If not + specified, defaults to 300 seconds (5 minutes) + type: integer + format: int64 + examples: + - 300 + magiclink_auth_uri: + description: >- + Your application's callback URL where users will be redirected after + clicking the magic link in their email. The link token will be appended as + a query parameter as link_token + type: string + examples: + - https://yourapp.com/auth/passwordless/callback + state: + description: >- + Custom state parameter that will be returned unchanged in the verification + response. Use this to maintain application state between the + authentication request and callback, such as the intended destination + after login + type: string + examples: + - d62ivasry29lso + template: + description: >- + Specifies the authentication intent for the passwordless request. Use + SIGNIN for existing users or SIGNUP for new user registration. This + affects the email template and user experience flow. + $ref: ./passwordlessTemplateType.yaml + examples: + - SIGNIN + template_variables: + description: >- + A set of key-value pairs to personalize the email template. + + + * You may include up to 30 key-value pairs. + + * The following variable names are reserved by the system and cannot be + supplied: `otp`, `expiry_time_relative`, `link`, `expire_time`, + `expiry_time`. + + * Every variable referenced in your email template must be included as a + key-value pair. + + + Use these variables to insert custom information, such as a team name, URL + or the user's employee ID. All variables are interpolated before the email + is sent, regardless of the email provider. + type: object + additionalProperties: + type: string + examples: + - custom_variable_key: custom_variable_value diff --git a/openapi/components/schemas/passwordlessSendPasswordlessResponse.yaml b/openapi/components/schemas/passwordlessSendPasswordlessResponse.yaml new file mode 100644 index 000000000..60c2446bd --- /dev/null +++ b/openapi/components/schemas/passwordlessSendPasswordlessResponse.yaml @@ -0,0 +1,37 @@ +type: object +properties: + auth_request_id: + description: >- + Unique identifier for this passwordless authentication request. Use this + ID to resend emails. + type: string + readOnly: true + examples: + - h5Y8kT5RVwaea5WEgW4n-6C-aO_-fuTUW7Vb9-Rh3AcY9qxZqQ + expires_at: + description: >- + Unix timestamp (seconds since epoch) when the passwordless authentication + will expire. After this time, the OTP or magic link will no longer be + valid. + type: string + format: int64 + readOnly: true + examples: + - 1748696575 + expires_in: + description: >- + Number of seconds from now until the passwordless authentication expires. + This is a convenience field calculated from the expires_at timestamp. + type: integer + format: int64 + readOnly: true + examples: + - 300 + passwordless_type: + description: >- + Type of passwordless authentication that was sent via email. OTP sends a + numeric code, LINK sends a clickable magic link, and LINK_OTP provides + both options for user convenience. + $ref: ./authpasswordlessPasswordlessType.yaml + examples: + - OTP diff --git a/openapi/components/schemas/passwordlessTemplateType.yaml b/openapi/components/schemas/passwordlessTemplateType.yaml new file mode 100644 index 000000000..47bce8b11 --- /dev/null +++ b/openapi/components/schemas/passwordlessTemplateType.yaml @@ -0,0 +1,4 @@ +type: string +enum: + - SIGNIN + - SIGNUP diff --git a/openapi/components/schemas/passwordlessVerifyPasswordLessRequest.yaml b/openapi/components/schemas/passwordlessVerifyPasswordLessRequest.yaml new file mode 100644 index 000000000..fd6686b48 --- /dev/null +++ b/openapi/components/schemas/passwordlessVerifyPasswordLessRequest.yaml @@ -0,0 +1,25 @@ +type: object +properties: + auth_request_id: + description: >- + The authentication request identifier returned from the send passwordless + email endpoint. Required when verifying OTP codes to link the verification + with the original request. + type: string + examples: + - h5Y8kT5RVwaea5WEgW4n-6C-aO_-fuTUW7Vb9-Rh3AcY9qxZqQ + code: + description: >- + The Verification Code (OTP) received via email. This is typically a + 6-digit numeric code that users enter manually to verify their identity. + type: string + examples: + - '123456' + link_token: + description: >- + The unique token from the magic link URL received via email. Extract this + token when users click the magic link and are redirected to your + application to later verify the user. + type: string + examples: + - afe9d61c-d80d-4020-a8ee-61765ab71cb3 diff --git a/openapi/components/schemas/passwordlessVerifyPasswordLessResponse.yaml b/openapi/components/schemas/passwordlessVerifyPasswordLessResponse.yaml new file mode 100644 index 000000000..07dfde42d --- /dev/null +++ b/openapi/components/schemas/passwordlessVerifyPasswordLessResponse.yaml @@ -0,0 +1,33 @@ +type: object +properties: + email: + description: >- + Email address of the successfully authenticated user. This confirms which + email account was verified through the passwordless flow. + type: string + readOnly: true + examples: + - john.doe@example.com + passwordless_type: + description: >- + The type of passwordless authentication that was successfully verified, + confirming which method the user completed. + $ref: ./authpasswordlessPasswordlessType.yaml + examples: + - OTP + state: + description: >- + The custom state parameter that was provided in the original + authentication request, returned unchanged. Use this to restore your + application's context after authentication. + type: string + readOnly: true + examples: + - kdt7yiag28t341fr1 + template: + description: >- + Specifies which email template to choose. For User Signin choose SIGNIN + and for User Signup use SIGNUP + $ref: ./passwordlessTemplateType.yaml + examples: + - SIGNIN diff --git a/openapi/components/schemas/protobufNullValue.yaml b/openapi/components/schemas/protobufNullValue.yaml new file mode 100644 index 000000000..12bf801c2 --- /dev/null +++ b/openapi/components/schemas/protobufNullValue.yaml @@ -0,0 +1,6 @@ +description: |- + `NullValue` is a singleton enumeration to represent the null value for the + `Value` type union. + + The JSON representation for `NullValue` is JSON `null`. +type: string diff --git a/openapi/components/schemas/rolesAddPermissionsToRoleResponse.yaml b/openapi/components/schemas/rolesAddPermissionsToRoleResponse.yaml new file mode 100644 index 000000000..e8cf21239 --- /dev/null +++ b/openapi/components/schemas/rolesAddPermissionsToRoleResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + permissions: + description: List of all permissions belonging to the role after addition + type: array + items: + type: object + $ref: ./rolesPermission.yaml diff --git a/openapi/components/schemas/rolesCreateOrganizationRoleResponse.yaml b/openapi/components/schemas/rolesCreateOrganizationRoleResponse.yaml new file mode 100644 index 000000000..5f89b49de --- /dev/null +++ b/openapi/components/schemas/rolesCreateOrganizationRoleResponse.yaml @@ -0,0 +1,4 @@ +type: object +properties: + role: + $ref: ./v1rolesRole.yaml diff --git a/openapi/components/schemas/rolesCreatePermissionResponse.yaml b/openapi/components/schemas/rolesCreatePermissionResponse.yaml new file mode 100644 index 000000000..bf007adee --- /dev/null +++ b/openapi/components/schemas/rolesCreatePermissionResponse.yaml @@ -0,0 +1,4 @@ +type: object +properties: + permission: + $ref: ./rolesPermission.yaml diff --git a/openapi/components/schemas/rolesCreateRoleResponse.yaml b/openapi/components/schemas/rolesCreateRoleResponse.yaml new file mode 100644 index 000000000..5090d09c3 --- /dev/null +++ b/openapi/components/schemas/rolesCreateRoleResponse.yaml @@ -0,0 +1,12 @@ +type: object +properties: + role: + description: >- + The created role object with system-generated ID and all configuration + details. + $ref: ./v1rolesRole.yaml + examples: + - description: Can edit content + display_name: Content Editor + id: role_1234abcd5678efgh + name: content_editor diff --git a/openapi/components/schemas/rolesGetOrganizationRoleResponse.yaml b/openapi/components/schemas/rolesGetOrganizationRoleResponse.yaml new file mode 100644 index 000000000..5f89b49de --- /dev/null +++ b/openapi/components/schemas/rolesGetOrganizationRoleResponse.yaml @@ -0,0 +1,4 @@ +type: object +properties: + role: + $ref: ./v1rolesRole.yaml diff --git a/openapi/components/schemas/rolesGetPermissionResponse.yaml b/openapi/components/schemas/rolesGetPermissionResponse.yaml new file mode 100644 index 000000000..bf007adee --- /dev/null +++ b/openapi/components/schemas/rolesGetPermissionResponse.yaml @@ -0,0 +1,4 @@ +type: object +properties: + permission: + $ref: ./rolesPermission.yaml diff --git a/openapi/components/schemas/rolesGetRoleResponse.yaml b/openapi/components/schemas/rolesGetRoleResponse.yaml new file mode 100644 index 000000000..69ae0f32d --- /dev/null +++ b/openapi/components/schemas/rolesGetRoleResponse.yaml @@ -0,0 +1,14 @@ +type: object +properties: + role: + description: >- + The complete role object with all metadata, permissions, and inheritance + details. + $ref: ./v1rolesRole.yaml + examples: + - dependent_roles_count: 2 + display_name: Content Editor + id: role_1234abcd5678efgh + name: content_editor + permissions: + - name: read:content diff --git a/openapi/components/schemas/rolesGetRoleUsersCountResponse.yaml b/openapi/components/schemas/rolesGetRoleUsersCountResponse.yaml new file mode 100644 index 000000000..23baf7b8d --- /dev/null +++ b/openapi/components/schemas/rolesGetRoleUsersCountResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + count: + description: Number of users associated with the role + type: string + format: int64 + examples: + - 10 diff --git a/openapi/components/schemas/rolesListDependentRolesResponse.yaml b/openapi/components/schemas/rolesListDependentRolesResponse.yaml new file mode 100644 index 000000000..47e3ff77d --- /dev/null +++ b/openapi/components/schemas/rolesListDependentRolesResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + roles: + description: List of dependent roles + type: array + items: + type: object + $ref: ./v1rolesRole.yaml diff --git a/openapi/components/schemas/rolesListEffectiveRolePermissionsResponse.yaml b/openapi/components/schemas/rolesListEffectiveRolePermissionsResponse.yaml new file mode 100644 index 000000000..6df5934be --- /dev/null +++ b/openapi/components/schemas/rolesListEffectiveRolePermissionsResponse.yaml @@ -0,0 +1,10 @@ +type: object +properties: + permissions: + description: >- + List of all effective permissions including those inherited from base + roles + type: array + items: + type: object + $ref: ./rolesPermission.yaml diff --git a/openapi/components/schemas/rolesListOrganizationRolesResponse.yaml b/openapi/components/schemas/rolesListOrganizationRolesResponse.yaml new file mode 100644 index 000000000..24f4f8e3a --- /dev/null +++ b/openapi/components/schemas/rolesListOrganizationRolesResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + roles: + description: List of roles objects + type: array + items: + type: object + $ref: ./v1rolesRole.yaml diff --git a/openapi/components/schemas/rolesListPermissionsResponse.yaml b/openapi/components/schemas/rolesListPermissionsResponse.yaml new file mode 100644 index 000000000..26d583aed --- /dev/null +++ b/openapi/components/schemas/rolesListPermissionsResponse.yaml @@ -0,0 +1,23 @@ +type: object +properties: + next_page_token: + description: Token to retrieve next page of results + type: string + examples: + - token_def456 + permissions: + type: array + items: + type: object + $ref: ./rolesPermission.yaml + prev_page_token: + description: Token to retrieve previous page of results + type: string + examples: + - token_def456 + total_size: + description: Total number of permissions available + type: integer + format: int64 + examples: + - 150 diff --git a/openapi/components/schemas/rolesListRolePermissionsResponse.yaml b/openapi/components/schemas/rolesListRolePermissionsResponse.yaml new file mode 100644 index 000000000..dd5be2999 --- /dev/null +++ b/openapi/components/schemas/rolesListRolePermissionsResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + permissions: + description: List of permissions directly assigned to the role + type: array + items: + type: object + $ref: ./rolesPermission.yaml diff --git a/openapi/components/schemas/rolesListRolesResponse.yaml b/openapi/components/schemas/rolesListRolesResponse.yaml new file mode 100644 index 000000000..88cf1ed1b --- /dev/null +++ b/openapi/components/schemas/rolesListRolesResponse.yaml @@ -0,0 +1,17 @@ +type: object +properties: + roles: + description: >- + List of all roles in the environment with their metadata and optionally + their permissions. + type: array + items: + type: object + $ref: ./v1rolesRole.yaml + examples: + - - display_name: Administrator + id: role_1234abcd5678efgh + name: admin + - display_name: Viewer + id: role_9876zyxw5432vuts + name: viewer diff --git a/openapi/components/schemas/rolesPermission.yaml b/openapi/components/schemas/rolesPermission.yaml new file mode 100644 index 000000000..8775a6d8a --- /dev/null +++ b/openapi/components/schemas/rolesPermission.yaml @@ -0,0 +1,20 @@ +type: object +title: Permission Entity +properties: + create_time: + type: string + format: date-time + description: + type: string + id: + type: string + is_scalekit_permission: + description: Indicates whether this permission is predefined by Scalekit + type: boolean + examples: + - true + name: + type: string + update_time: + type: string + format: date-time diff --git a/openapi/components/schemas/rolesPermissionType.yaml b/openapi/components/schemas/rolesPermissionType.yaml new file mode 100644 index 000000000..e8bee763a --- /dev/null +++ b/openapi/components/schemas/rolesPermissionType.yaml @@ -0,0 +1,4 @@ +type: string +enum: + - SCALEKIT + - ENVIRONMENT diff --git a/openapi/components/schemas/rolesRolePermission.yaml b/openapi/components/schemas/rolesRolePermission.yaml new file mode 100644 index 000000000..3c058b6a9 --- /dev/null +++ b/openapi/components/schemas/rolesRolePermission.yaml @@ -0,0 +1,20 @@ +type: object +title: RolePermissions represents a permission with role source information +properties: + create_time: + type: string + format: date-time + description: + type: string + id: + type: string + name: + type: string + role_name: + description: Name of the role from which this permission was sourced + type: string + examples: + - admin_role + update_time: + type: string + format: date-time diff --git a/openapi/components/schemas/rolesUpdateDefaultOrganizationRolesResponse.yaml b/openapi/components/schemas/rolesUpdateDefaultOrganizationRolesResponse.yaml new file mode 100644 index 000000000..2793fcff5 --- /dev/null +++ b/openapi/components/schemas/rolesUpdateDefaultOrganizationRolesResponse.yaml @@ -0,0 +1,10 @@ +type: object +properties: + default_member: + description: Updated default member role + $ref: ./v1rolesRole.yaml + examples: + - description: Role for regular members + display_name: Member Role + id: role_0987654321 + name: member diff --git a/openapi/components/schemas/rolesUpdateDefaultRole.yaml b/openapi/components/schemas/rolesUpdateDefaultRole.yaml new file mode 100644 index 000000000..5110612d2 --- /dev/null +++ b/openapi/components/schemas/rolesUpdateDefaultRole.yaml @@ -0,0 +1,9 @@ +type: object +properties: + id: + type: string + name: + description: Unique name of the role + type: string + examples: + - creator diff --git a/openapi/components/schemas/rolesUpdateDefaultRolesRequest.yaml b/openapi/components/schemas/rolesUpdateDefaultRolesRequest.yaml new file mode 100644 index 000000000..c45658514 --- /dev/null +++ b/openapi/components/schemas/rolesUpdateDefaultRolesRequest.yaml @@ -0,0 +1,34 @@ +type: object +properties: + default_creator: + description: Default creator role (deprecated - use default_creator_role field instead) + $ref: ./rolesUpdateDefaultRole.yaml + examples: + - description: Role for creating resources + display_name: Creator Role + id: role_1234567890 + name: creator + default_creator_role: + description: >- + Name of the role to set as the default creator role. This role will be + automatically assigned to users who create new resources in the + environment. Must be a valid role name that exists in the environment. + type: string + examples: + - creator + default_member: + description: Default member role (deprecated - use default_member_role field instead) + $ref: ./rolesUpdateDefaultRole.yaml + examples: + - description: Role for regular members + display_name: Member Role + id: role_0987654321 + name: member + default_member_role: + description: >- + Name of the role to set as the default member role. This role will be + automatically assigned to new users when they join the environment. Must + be a valid role name that exists in the environment. + type: string + examples: + - member diff --git a/openapi/components/schemas/rolesUpdateDefaultRolesResponse.yaml b/openapi/components/schemas/rolesUpdateDefaultRolesResponse.yaml new file mode 100644 index 000000000..02bfb2ccb --- /dev/null +++ b/openapi/components/schemas/rolesUpdateDefaultRolesResponse.yaml @@ -0,0 +1,22 @@ +type: object +properties: + default_creator: + description: >- + The role that is now set as the default creator role for the environment. + Contains complete role information including permissions and metadata. + $ref: ./v1rolesRole.yaml + examples: + - description: Role for creating resources + display_name: Creator Role + id: role_1234567890 + name: creator + default_member: + description: >- + The role that is now set as the default member role for the environment. + Contains complete role information including permissions and metadata. + $ref: ./v1rolesRole.yaml + examples: + - description: Role for regular members + display_name: Member Role + id: role_0987654321 + name: member diff --git a/openapi/components/schemas/rolesUpdateOrganizationRoleResponse.yaml b/openapi/components/schemas/rolesUpdateOrganizationRoleResponse.yaml new file mode 100644 index 000000000..5f89b49de --- /dev/null +++ b/openapi/components/schemas/rolesUpdateOrganizationRoleResponse.yaml @@ -0,0 +1,4 @@ +type: object +properties: + role: + $ref: ./v1rolesRole.yaml diff --git a/openapi/components/schemas/rolesUpdatePermissionResponse.yaml b/openapi/components/schemas/rolesUpdatePermissionResponse.yaml new file mode 100644 index 000000000..bf007adee --- /dev/null +++ b/openapi/components/schemas/rolesUpdatePermissionResponse.yaml @@ -0,0 +1,4 @@ +type: object +properties: + permission: + $ref: ./rolesPermission.yaml diff --git a/openapi/components/schemas/rolesUpdateRoleResponse.yaml b/openapi/components/schemas/rolesUpdateRoleResponse.yaml new file mode 100644 index 000000000..efe00858f --- /dev/null +++ b/openapi/components/schemas/rolesUpdateRoleResponse.yaml @@ -0,0 +1,10 @@ +type: object +properties: + role: + description: The updated role object with all current configuration details. + $ref: ./v1rolesRole.yaml + examples: + - description: Can edit and approve content + display_name: Senior Editor + id: role_1234abcd5678efgh + name: content_editor diff --git a/openapi/components/schemas/sessionsAuthenticatedClients.yaml b/openapi/components/schemas/sessionsAuthenticatedClients.yaml new file mode 100644 index 000000000..fb043198e --- /dev/null +++ b/openapi/components/schemas/sessionsAuthenticatedClients.yaml @@ -0,0 +1,17 @@ +description: >- + AuthenticatedClients represents an authenticated client in a session along + with its organization context. +type: object +properties: + client_id: + description: Unique identifier of the authenticated client application. + type: string + examples: + - skc_1234567890 + organization_id: + description: >- + Active or last active Organization ID associated with the authenticated + client. + type: string + examples: + - org_1234567890 diff --git a/openapi/components/schemas/sessionsDeviceDetails.yaml b/openapi/components/schemas/sessionsDeviceDetails.yaml new file mode 100644 index 000000000..9df5835cd --- /dev/null +++ b/openapi/components/schemas/sessionsDeviceDetails.yaml @@ -0,0 +1,63 @@ +type: object +properties: + browser: + description: >- + Browser name and family extracted from the user agent. Examples: Chrome, + Safari, Firefox, Edge, Mobile Safari. + type: string + examples: + - Chrome + browser_version: + description: >- + Version of the browser application. Represents the specific release + version of the browser being used. + type: string + examples: + - 120.0.0.0 + device_type: + description: >- + Categorized device type classification. Possible values: 'desktop' + (traditional computers), 'mobile' (smartphones and small tablets), + 'tablet' (large tablets), 'other'. Useful for displaying session + information by device category. + type: string + examples: + - desktop + ip: + description: >- + IP address of the device that initiated the session. This is the + public-facing IP address used to connect to the application. Useful for + security audits and geographic distribution analysis. + type: string + examples: + - 192.0.2.1 + location: + description: >- + Geographic location information derived from IP address geolocation. + Includes country, region, city, and coordinates. Note: Based on IP + location data and may not represent the user's exact physical location. + $ref: ./v1sessionsLocation.yaml + os: + description: >- + Operating system name extracted from the user agent and device headers. + Examples: macOS, Windows, Linux, iOS, Android. + type: string + examples: + - macOS + os_version: + description: >- + Version of the operating system. Represents the specific OS release the + device is running. + type: string + examples: + - '14.2' + user_agent: + description: >- + Complete HTTP User-Agent header string from the client request. Contains + browser type, version, and operating system information. Used for detailed + device fingerprinting and user agent analysis. + type: string + examples: + - >- + Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 + (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 diff --git a/openapi/components/schemas/sessionsRevokeAllUserSessionsResponse.yaml b/openapi/components/schemas/sessionsRevokeAllUserSessionsResponse.yaml new file mode 100644 index 000000000..4a1818f07 --- /dev/null +++ b/openapi/components/schemas/sessionsRevokeAllUserSessionsResponse.yaml @@ -0,0 +1,18 @@ +type: object +properties: + revoked_sessions: + description: >- + List of all sessions that were revoked, including detailed information for + each revoked session with IDs, timestamps, and device details. + type: array + items: + type: object + $ref: ./sessionsRevokedSessionDetails.yaml + total_revoked: + description: >- + Total count of active sessions that were revoked. Useful for confirmation + and audit logging. + type: integer + format: int64 + examples: + - 5 diff --git a/openapi/components/schemas/sessionsRevokeSessionResponse.yaml b/openapi/components/schemas/sessionsRevokeSessionResponse.yaml new file mode 100644 index 000000000..616d64a01 --- /dev/null +++ b/openapi/components/schemas/sessionsRevokeSessionResponse.yaml @@ -0,0 +1,7 @@ +type: object +properties: + revoked_session: + description: >- + Details of the revoked session including session ID, user ID, creation and + revocation timestamps, and final device information. + $ref: ./sessionsRevokedSessionDetails.yaml diff --git a/openapi/components/schemas/sessionsRevokedSessionDetails.yaml b/openapi/components/schemas/sessionsRevokedSessionDetails.yaml new file mode 100644 index 000000000..877bd322f --- /dev/null +++ b/openapi/components/schemas/sessionsRevokedSessionDetails.yaml @@ -0,0 +1,77 @@ +type: object +properties: + absolute_expires_at: + description: >- + The absolute expiration timestamp that was configured for this session + before revocation. Represents the hard deadline regardless of activity. + type: string + format: date-time + examples: + - '2025-01-22T10:30:00Z' + created_at: + description: >- + Timestamp indicating when the session was originally created before + revocation. + type: string + format: date-time + examples: + - '2025-01-15T10:30:00Z' + expired_at: + description: >- + Timestamp when the session was actually terminated. Set to the revocation + time when the session is revoked. + type: string + format: date-time + examples: + - '2025-01-15T12:00:00Z' + idle_expires_at: + description: >- + The idle expiration timestamp that was configured for this session before + revocation. Represents when the session would have expired due to + inactivity. + type: string + format: date-time + examples: + - '2025-01-15T11:30:00Z' + last_active_at: + description: >- + Timestamp of the last recorded user activity in this session before + revocation. Helps identify inactive sessions that were revoked. + type: string + format: date-time + examples: + - '2025-01-15T10:55:30Z' + logout_at: + description: >- + Timestamp when the user explicitly logged out (if applicable). Null if the + session was revoked without prior logout. + type: string + format: date-time + examples: + - '2025-01-15T14:00:00Z' + session_id: + description: >- + Unique identifier for the revoked session. System-generated read-only + field. + type: string + examples: + - ses_1234567890123456 + status: + description: >- + Status of the session after revocation. Always 'revoked' since only active + sessions can be revoked. Sessions that were already expired or logged out + are not included in the revocation response. + type: string + examples: + - revoked + updated_at: + description: Timestamp indicating when the session was last modified before revocation. + type: string + format: date-time + examples: + - '2025-01-15T10:45:00Z' + user_id: + description: Unique identifier for the user who owned this session. + type: string + examples: + - usr_1234567890123456 diff --git a/openapi/components/schemas/sessionsSessionDetails.yaml b/openapi/components/schemas/sessionsSessionDetails.yaml new file mode 100644 index 000000000..5521545f5 --- /dev/null +++ b/openapi/components/schemas/sessionsSessionDetails.yaml @@ -0,0 +1,122 @@ +type: object +properties: + absolute_expires_at: + description: >- + Hard expiration timestamp for the session regardless of user activity. The + session will be forcibly terminated at this time. This represents the + maximum session lifetime from creation. + type: string + format: date-time + examples: + - '2025-01-22T10:30:00Z' + authenticated_clients: + description: >- + Details of the authenticated clients for this session: client ID and + organization context. + type: array + items: + type: object + $ref: ./sessionsAuthenticatedClients.yaml + authenticated_organizations: + description: >- + List of organization IDs that have been authenticated for this user within + the current session. Contains all organizations where the user has + successfully completed SSO or authentication. + type: array + items: + type: string + examples: + - - org_123 + - org_456 + created_at: + description: >- + Timestamp indicating when the session was created. This is set once at + session creation and remains constant throughout the session lifetime. + type: string + format: date-time + examples: + - '2025-01-15T10:30:00Z' + device: + description: >- + Complete device metadata associated with this session including browser, + operating system, device type, and geographic location based on IP + address. + $ref: ./sessionsDeviceDetails.yaml + expired_at: + description: >- + Timestamp when the session was terminated. Null if the session is still + active. Set when the session expires due to reaching idle_expires_at or + absolute_expires_at timeout, or when administratively revoked. Not set for + user-initiated logout (see logout_at instead). + type: string + format: date-time + examples: + - '2025-01-15T12:00:00Z' + idle_expires_at: + description: >- + Projected expiration timestamp if the session remains idle without user + activity. This timestamp is recalculated with each user activity. Session + will be automatically terminated at this time if no activity occurs. + type: string + format: date-time + examples: + - '2025-01-15T11:30:00Z' + last_active_at: + description: >- + Timestamp of the most recent user activity detected in this session. + Updated on each API request or user interaction. Used to determine if a + session has exceeded the idle timeout threshold. + type: string + format: date-time + examples: + - '2025-01-15T10:55:30Z' + logout_at: + description: >- + Timestamp when the user explicitly logged out from the session. Null if + the user has not logged out. When set, indicates the session ended due to + explicit user logout rather than timeout. + type: string + format: date-time + examples: + - '2025-01-15T14:00:00Z' + organization_id: + description: >- + Organization ID for the user's most recently active organization within + this session. This represents the primary organization context for the + current session. + type: string + examples: + - org_1234567890123456 + session_id: + description: >- + Unique identifier for the session. System-generated read-only field used + to reference this session. + type: string + examples: + - ses_1234567890123456 + status: + description: >- + Current operational status of the session. Possible values: 'active' + (session is valid and requests are allowed), 'expired' (session terminated + due to idle or absolute timeout), 'revoked' (session was administratively + revoked), 'logout' (user explicitly logged out). Use this to determine if + the session can be used for new requests. + type: string + examples: + - active + updated_at: + description: >- + Timestamp indicating when the session was last updated. Updated whenever + session state changes such as organization context changes or metadata + updates. + type: string + format: date-time + examples: + - '2025-01-15T10:45:00Z' + user_id: + description: >- + Unique identifier for the user who owns and is authenticated within this + session. + type: string + examples: + - usr_1234567890123456 diff --git a/openapi/components/schemas/sessionsUserSessionDetails.yaml b/openapi/components/schemas/sessionsUserSessionDetails.yaml new file mode 100644 index 000000000..f56fc8fcc --- /dev/null +++ b/openapi/components/schemas/sessionsUserSessionDetails.yaml @@ -0,0 +1,33 @@ +type: object +properties: + next_page_token: + description: >- + Pagination token for retrieving the next page of results. Empty string if + there are no more pages (you have reached the final page of results). + type: string + examples: + - eyJwYWdlIjogMiwgImxhc3RfaWQiOiAic2VzXzEyMzQ1In0= + prev_page_token: + description: >- + Pagination token for retrieving the previous page of results. Empty string + for the first page. Use this to navigate backward through result pages. + type: string + examples: + - eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInNlc183OTAxIn0= + sessions: + description: >- + Array of session objects for the requested user. May contain fewer entries + than the requested page_size when reaching the final page of results. + type: array + items: + type: object + $ref: ./sessionsSessionDetails.yaml + total_size: + description: >- + Total number of sessions matching the applied filter criteria, regardless + of pagination. This represents the complete result set size before + pagination is applied. + type: integer + format: int64 + examples: + - 42 diff --git a/openapi/components/schemas/sessionsUserSessionFilter.yaml b/openapi/components/schemas/sessionsUserSessionFilter.yaml new file mode 100644 index 000000000..ffe6def48 --- /dev/null +++ b/openapi/components/schemas/sessionsUserSessionFilter.yaml @@ -0,0 +1,31 @@ +type: object +properties: + end_time: + description: >- + Filter to include only sessions created on or before this timestamp. + Optional. Uses RFC 3339 format. Must be after start_time if both are + specified. + type: string + format: date-time + examples: + - '2025-12-31T23:59:59Z' + start_time: + description: >- + Filter to include only sessions created on or after this timestamp. + Optional. Uses RFC 3339 format. Useful for querying sessions within a + specific time window. + type: string + format: date-time + examples: + - '2025-01-01T00:00:00Z' + status: + description: >- + Filter sessions by one or more status values. Possible values: 'active', + 'expired', 'revoked', 'logout'. Leave empty to include all statuses. + Multiple values use OR logic (e.g., status=['active', 'expired'] returns + sessions that are either active OR expired). + type: array + items: + type: string + examples: + - - active diff --git a/openapi/components/schemas/toolsExecuteToolRequest.yaml b/openapi/components/schemas/toolsExecuteToolRequest.yaml new file mode 100644 index 000000000..e16fee58f --- /dev/null +++ b/openapi/components/schemas/toolsExecuteToolRequest.yaml @@ -0,0 +1,64 @@ +type: object +properties: + agent_run_id: + description: >- + Optional. Customer-supplied identifier grouping multiple tool calls into a + single agent run. Useful for correlating logs across an agentic workflow. + type: string + examples: + - run_abc123 + connected_account_id: + description: >- + Optional. The unique ID of the connected account. Use this to directly + identify the connected account instead of using identifier + connector + combination. + type: string + examples: + - ca_123 + connector: + description: >- + Optional. The name of the connector/provider (e.g., 'Google Workspace', + 'Slack', 'Notion'). Alphanumeric characters, spaces, hyphens, underscores, + and colons are allowed. Use this in combination with identifier to + identify the connected account. + type: string + examples: + - Google Workspace + identifier: + description: >- + Optional. The unique identifier for the connected account within the + third-party service (e.g., email address, user ID, workspace identifier). + Use this in combination with connector to identify the connected account. + type: string + examples: + - user@example.com + organization_id: + description: >- + Optional. The organization ID to scope the connected account lookup. Use + this to narrow down the search when the same identifier exists across + multiple organizations. + type: string + examples: + - org_123 + params: + description: >- + JSON object containing the parameters required for tool execution. The + structure depends on the specific tool being executed. + type: object + examples: + - body: Hello World + subject: Hello + to: user@example.com + tool_name: + description: Name of the tool to execute + type: string + examples: + - send_email + user_id: + description: >- + Optional. The user ID to scope the connected account lookup. Use this to + narrow down the search when the same identifier exists across multiple + users. + type: string + examples: + - user_123 diff --git a/openapi/components/schemas/toolsExecuteToolResponse.yaml b/openapi/components/schemas/toolsExecuteToolResponse.yaml new file mode 100644 index 000000000..965cd87f1 --- /dev/null +++ b/openapi/components/schemas/toolsExecuteToolResponse.yaml @@ -0,0 +1,14 @@ +type: object +properties: + data: + description: Free-flowing JSON parameters for the tool execution + type: object + examples: + - body: Hello World + subject: Hello + to: user@example.com + execution_id: + description: Unique identifier for the tool execution + type: string + examples: + - '123456789' diff --git a/openapi/components/schemas/usersCreateMembershipResponse.yaml b/openapi/components/schemas/usersCreateMembershipResponse.yaml new file mode 100644 index 000000000..5a4b62aad --- /dev/null +++ b/openapi/components/schemas/usersCreateMembershipResponse.yaml @@ -0,0 +1,4 @@ +type: object +properties: + user: + $ref: ./usersUser.yaml diff --git a/openapi/components/schemas/usersCreateUser.yaml b/openapi/components/schemas/usersCreateUser.yaml new file mode 100644 index 000000000..708f7a91c --- /dev/null +++ b/openapi/components/schemas/usersCreateUser.yaml @@ -0,0 +1,36 @@ +type: object +properties: + email: + description: >- + Primary email address for the user. Must be unique across the environment + and valid per RFC 5322. + type: string + examples: + - user@example.com + external_id: + description: >- + Your application's unique identifier for this organization, used to link + Scalekit with your system. + type: string + examples: + - ext_12345a67b89c + membership: + description: >- + List of organization memberships. Automatically populated based on group + assignments. + $ref: ./v1usersCreateMembership.yaml + metadata: + description: >- + Custom key-value pairs for storing additional user context. Keys (3-25 + chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + user_profile: + description: >- + User's personal information including name, address, and other profile + attributes. + $ref: ./usersCreateUserProfile.yaml diff --git a/openapi/components/schemas/usersCreateUserAndMembershipResponse.yaml b/openapi/components/schemas/usersCreateUserAndMembershipResponse.yaml new file mode 100644 index 000000000..5a4b62aad --- /dev/null +++ b/openapi/components/schemas/usersCreateUserAndMembershipResponse.yaml @@ -0,0 +1,4 @@ +type: object +properties: + user: + $ref: ./usersUser.yaml diff --git a/openapi/components/schemas/usersCreateUserProfile.yaml b/openapi/components/schemas/usersCreateUserProfile.yaml new file mode 100644 index 000000000..7678afe60 --- /dev/null +++ b/openapi/components/schemas/usersCreateUserProfile.yaml @@ -0,0 +1,76 @@ +type: object +properties: + custom_attributes: + description: >- + Custom attributes for extended user profile data. Keys (3-25 chars), + values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + security_clearance: level2 + family_name: + description: User's family name. Maximum 255 characters. + type: string + examples: + - Doe + gender: + description: User's gender identity. + type: string + examples: + - male + given_name: + description: User's given name. Maximum 255 characters. + type: string + examples: + - John + groups: + description: >- + List of group names the user belongs to. Each group name must be 1-250 + characters + type: array + items: + type: string + examples: + - - engineering + - managers + locale: + description: >- + User's localization preference in BCP-47 format. Defaults to organization + settings. + type: string + examples: + - en-US + metadata: + description: >- + System-managed key-value pairs for internal tracking. Keys (3-25 chars), + values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - account_status: active + signup_source: mobile_app + name: + description: Full name in display format. Typically combines first_name and last_name. + type: string + examples: + - John Michael Doe + phone_number: + description: >- + Phone number in E.164 international format. Required for SMS-based + authentication. + type: string + examples: + - '+14155552671' + picture: + description: URL to the user's profile picture or avatar. + type: string + examples: + - https://example.com/avatar.jpg + preferred_username: + description: User's preferred username for display purposes. + type: string + examples: + - John Michael Doe diff --git a/openapi/components/schemas/usersGetUserResponse.yaml b/openapi/components/schemas/usersGetUserResponse.yaml new file mode 100644 index 000000000..5a4b62aad --- /dev/null +++ b/openapi/components/schemas/usersGetUserResponse.yaml @@ -0,0 +1,4 @@ +type: object +properties: + user: + $ref: ./usersUser.yaml diff --git a/openapi/components/schemas/usersInvite.yaml b/openapi/components/schemas/usersInvite.yaml new file mode 100644 index 000000000..d07754b42 --- /dev/null +++ b/openapi/components/schemas/usersInvite.yaml @@ -0,0 +1,48 @@ +type: object +properties: + created_at: + description: Timestamp when the invite was originally created. + type: string + format: date-time + examples: + - '2025-07-10T08:00:00Z' + expires_at: + description: The time at which the invite expires. + type: string + format: date-time + examples: + - '2025-12-31T23:59:59Z' + inviter_email: + description: Identifier of the user or system that initiated the invite. + type: string + examples: + - admin@example.com + organization_id: + description: The organization to which the invite belongs. + type: string + examples: + - org_987654321 + resent_at: + description: Timestamp when the invite was last resent, if applicable. + type: string + format: date-time + examples: + - '2025-07-15T09:30:00Z' + resent_count: + description: Number of times the invite has been resent. + type: integer + format: int32 + examples: + - 2 + status: + description: Current status of the invite (e.g., pending, accepted, expired, revoked). + type: string + examples: + - pending_invite + user_id: + description: >- + User ID to whom the invite is sent. May be empty if the user has not + signed up yet. + type: string + examples: + - usr_123456 diff --git a/openapi/components/schemas/usersListOrganizationUsersResponse.yaml b/openapi/components/schemas/usersListOrganizationUsersResponse.yaml new file mode 100644 index 000000000..622c7ab24 --- /dev/null +++ b/openapi/components/schemas/usersListOrganizationUsersResponse.yaml @@ -0,0 +1,32 @@ +type: object +properties: + next_page_token: + description: >- + Opaque token for retrieving the next page of results. Empty if there are + no more pages. + type: string + examples: + - eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0= + prev_page_token: + description: >- + Opaque token for retrieving the previous page of results. Empty for the + first page. + type: string + examples: + - eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9 + total_size: + description: >- + Total number of users matching the request criteria, regardless of + pagination. + type: integer + format: int64 + examples: + - 1042 + users: + description: >- + List of user objects for the current page. May contain fewer entries than + requested page_size. + type: array + items: + type: object + $ref: ./usersUser.yaml diff --git a/openapi/components/schemas/usersListUserPermissionsResponse.yaml b/openapi/components/schemas/usersListUserPermissionsResponse.yaml new file mode 100644 index 000000000..53c967305 --- /dev/null +++ b/openapi/components/schemas/usersListUserPermissionsResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + permissions: + description: List of permissions the user has access to + type: array + items: + type: object + $ref: ./usersPermission.yaml diff --git a/openapi/components/schemas/usersListUserRolesResponse.yaml b/openapi/components/schemas/usersListUserRolesResponse.yaml new file mode 100644 index 000000000..3773814b8 --- /dev/null +++ b/openapi/components/schemas/usersListUserRolesResponse.yaml @@ -0,0 +1,8 @@ +type: object +properties: + roles: + description: List of roles assigned to the user + type: array + items: + type: object + $ref: ./commonsRole.yaml diff --git a/openapi/components/schemas/usersListUsersResponse.yaml b/openapi/components/schemas/usersListUsersResponse.yaml new file mode 100644 index 000000000..e20573b7a --- /dev/null +++ b/openapi/components/schemas/usersListUsersResponse.yaml @@ -0,0 +1,30 @@ +type: object +properties: + next_page_token: + description: >- + Token for retrieving the next page of results. Empty if there are no more + pages. + type: string + examples: + - eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0= + prev_page_token: + description: >- + Token for retrieving the previous page of results. Empty if this is the + first page. + type: string + examples: + - eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9 + total_size: + description: >- + Total number of users matching the request criteria, regardless of + pagination. + type: integer + format: int64 + examples: + - 1042 + users: + description: List of users. + type: array + items: + type: object + $ref: ./usersUser.yaml diff --git a/openapi/components/schemas/usersPermission.yaml b/openapi/components/schemas/usersPermission.yaml new file mode 100644 index 000000000..aeb0f039c --- /dev/null +++ b/openapi/components/schemas/usersPermission.yaml @@ -0,0 +1,18 @@ +type: object +properties: + description: + description: Description of what the permission allows + type: string + examples: + - Allows creating new user accounts + id: + description: Unique identifier for the permission + type: string + readOnly: true + examples: + - perm_1234abcd5678efgh + name: + description: Unique name identifier for the permission + type: string + examples: + - users:create diff --git a/openapi/components/schemas/usersResendInviteResponse.yaml b/openapi/components/schemas/usersResendInviteResponse.yaml new file mode 100644 index 000000000..bcf0c3796 --- /dev/null +++ b/openapi/components/schemas/usersResendInviteResponse.yaml @@ -0,0 +1,13 @@ +type: object +properties: + invite: + description: >- + Updated invitation object containing the resent invitation details, + including new expiration time and incremented resend counter. + $ref: ./usersInvite.yaml + examples: + - expires_at: '2025-12-31T23:59:59Z' + organization_id: org_123 + resent_count: 2 + status: pending_invite + user_id: usr_456 diff --git a/openapi/components/schemas/usersSearchOrganizationUsersResponse.yaml b/openapi/components/schemas/usersSearchOrganizationUsersResponse.yaml new file mode 100644 index 000000000..afea25037 --- /dev/null +++ b/openapi/components/schemas/usersSearchOrganizationUsersResponse.yaml @@ -0,0 +1,30 @@ +type: object +properties: + next_page_token: + description: >- + Token for retrieving the next page of results. Empty if there are no more + pages. + type: string + examples: + - eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0= + prev_page_token: + description: >- + Token for retrieving the previous page of results. Empty if this is the + first page. + type: string + examples: + - eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9 + total_size: + description: >- + Total number of users matching the request criteria, regardless of + pagination. + type: integer + format: int64 + examples: + - 1042 + users: + description: List of matching users. + type: array + items: + type: object + $ref: ./usersUser.yaml diff --git a/openapi/components/schemas/usersSearchUsersResponse.yaml b/openapi/components/schemas/usersSearchUsersResponse.yaml new file mode 100644 index 000000000..afea25037 --- /dev/null +++ b/openapi/components/schemas/usersSearchUsersResponse.yaml @@ -0,0 +1,30 @@ +type: object +properties: + next_page_token: + description: >- + Token for retrieving the next page of results. Empty if there are no more + pages. + type: string + examples: + - eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0= + prev_page_token: + description: >- + Token for retrieving the previous page of results. Empty if this is the + first page. + type: string + examples: + - eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9 + total_size: + description: >- + Total number of users matching the request criteria, regardless of + pagination. + type: integer + format: int64 + examples: + - 1042 + users: + description: List of matching users. + type: array + items: + type: object + $ref: ./usersUser.yaml diff --git a/openapi/components/schemas/usersUpdateMembershipResponse.yaml b/openapi/components/schemas/usersUpdateMembershipResponse.yaml new file mode 100644 index 000000000..5a4b62aad --- /dev/null +++ b/openapi/components/schemas/usersUpdateMembershipResponse.yaml @@ -0,0 +1,4 @@ +type: object +properties: + user: + $ref: ./usersUser.yaml diff --git a/openapi/components/schemas/usersUpdateUserProfile.yaml b/openapi/components/schemas/usersUpdateUserProfile.yaml new file mode 100644 index 000000000..cec063010 --- /dev/null +++ b/openapi/components/schemas/usersUpdateUserProfile.yaml @@ -0,0 +1,138 @@ +type: object +properties: + custom_attributes: + description: >- + Updates custom attributes for extended user profile data and + application-specific information. Use this field to store + business-specific user data like department, job title, security + clearances, project assignments, or any other organizational attributes + your application requires. Unlike system metadata, these attributes are + typically managed by administrators or applications and are visible to end + users. Keys must be 3-25 characters, values must be 1-256 characters, with + a maximum of 20 key-value pairs. + type: object + additionalProperties: + type: string + examples: + - department: engineering + security_clearance: level2 + family_name: + description: >- + Updates the user's family name (last name or surname). Use this field to + modify how the user's last name appears throughout the system. Maximum 255 + characters allowed. + type: string + examples: + - Doe + first_name: + description: >- + [DEPRECATED] Use given_name instead. User's given name. Maximum 200 + characters. + type: string + examples: + - John + gender: + description: >- + Updates the user's gender identity information. Use this field to store + the user's gender identity for personalization, compliance, or reporting + purposes. This field supports any string value to accommodate diverse + gender identities and should be handled with appropriate privacy + considerations according to your organization's policies. + type: string + examples: + - male + given_name: + description: >- + Updates the user's given name (first name). Use this field to modify how + the user's first name appears in the system and user interfaces. Maximum + 255 characters allowed. + type: string + examples: + - John + groups: + description: >- + Updates the list of group names the user belongs to within the + organization. Use this field to manage the user's group memberships for + role-based access control, team assignments, or organizational structure. + Groups are typically used for permission management and collaborative + access. Each group name must be unique within the list, 1-250 characters + long, with a maximum of 50 groups per user. + type: array + items: + type: string + examples: + - - engineering + - managers + last_name: + description: >- + [DEPRECATED] Use family_name instead. User's family name. Maximum 200 + characters. + type: string + examples: + - Doe + locale: + description: >- + Updates the user's preferred language and region settings using BCP-47 + format codes. Use this field to customize the user's experience with + localized content, date formats, number formatting, and UI language. When + not specified, the user inherits the organization's default locale + settings. Common values include `en-US`, `en-GB`, `fr-FR`, `de-DE`, and + `es-ES`. + type: string + examples: + - en-US + metadata: + description: >- + Updates system-managed key-value pairs for internal tracking and + operational data. Use this field to store system-generated metadata like + account status, signup source, last activity tracking, or + integration-specific identifiers. These fields are typically managed by + automated processes rather than direct user input. Keys must be 3-25 + characters, values must be 1-256 characters, with a maximum of 20 + key-value pairs. + type: object + additionalProperties: + type: string + examples: + - account_status: active + signup_source: mobile_app + name: + description: >- + Updates the user's complete display name. Use this field when you want to + set the full name as a single string rather than using separate given and + family names. This name appears in user interfaces, reports, and anywhere + a formatted display name is needed. + type: string + examples: + - John Doe + phone_number: + description: >- + Updates the user's phone number in E.164 international format. Use this + field to enable SMS-based authentication methods, two-factor + authentication, or phone-based account recovery. The phone number must + include the country code and be formatted according to E.164 standards + (e.g., `+1` for US numbers). This field is required when enabling SMS + authentication features. + type: string + examples: + - '+14155552671' + picture: + description: >- + Updates the URL to the user's profile picture or avatar image. Use this + field to set or change the user's profile photo that appears in user + interfaces, directory listings, and collaborative features. The URL should + point to a publicly accessible image file. Supported formats typically + include JPEG, PNG, and GIF. Maximum URL length is 2048 characters. + type: string + examples: + - https://example.com/avatar.jpg + preferred_username: + description: >- + Updates the user's preferred username for display and identification + purposes. Use this field to set a custom username that the user prefers to + be known by, which may differ from their email or formal name. This + username appears in user interfaces, mentions, and informal + communications. Maximum 512 characters allowed. + type: string + examples: + - John Michael Doe diff --git a/openapi/components/schemas/usersUpdateUserResponse.yaml b/openapi/components/schemas/usersUpdateUserResponse.yaml new file mode 100644 index 000000000..5a4b62aad --- /dev/null +++ b/openapi/components/schemas/usersUpdateUserResponse.yaml @@ -0,0 +1,4 @@ +type: object +properties: + user: + $ref: ./usersUser.yaml diff --git a/openapi/components/schemas/usersUser.yaml b/openapi/components/schemas/usersUser.yaml new file mode 100644 index 000000000..96d7dd7bd --- /dev/null +++ b/openapi/components/schemas/usersUser.yaml @@ -0,0 +1,65 @@ +type: object +properties: + create_time: + description: >- + Timestamp when the user account was initially created. Automatically set + by the server. + type: string + format: date-time + readOnly: true + email: + description: >- + Primary email address for the user. Must be unique across the environment + and valid per RFC 5322. + type: string + examples: + - user@example.com + external_id: + description: >- + Your application's unique identifier for this organization, used to link + Scalekit with your system. + type: string + examples: + - ext_12345a67b89c + id: + description: Unique system-generated identifier for the user. Immutable once created. + type: string + examples: + - usr_1234abcd5678efgh + last_login_time: + description: >- + Timestamp of the user's most recent successful authentication. Updated + automatically. + type: string + format: date-time + readOnly: true + memberships: + description: >- + List of organization memberships. Automatically populated based on group + assignments. + type: array + items: + type: object + $ref: ./commonsOrganizationMembership.yaml + metadata: + description: >- + Custom key-value pairs for storing additional user context. Keys (3-25 + chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + update_time: + description: >- + Timestamp of the last modification to the user account. Automatically + updated by the server. + type: string + format: date-time + readOnly: true + user_profile: + description: >- + User's personal information including name, address, and other profile + attributes. + $ref: ./commonsUserProfile.yaml diff --git a/openapi/components/schemas/v1connected_accountsCreateConnectedAccount.yaml b/openapi/components/schemas/v1connected_accountsCreateConnectedAccount.yaml new file mode 100644 index 000000000..6c71918a9 --- /dev/null +++ b/openapi/components/schemas/v1connected_accountsCreateConnectedAccount.yaml @@ -0,0 +1,27 @@ +type: object +title: >- + Payload for creating a new connected account - authorization details are + optional +properties: + api_config: + description: >- + Optional JSON configuration for connector-specific API settings such as + rate limits, custom API endpoints, timeouts, or feature flags. + type: object + examples: + - base_url: https://api.custom-domain.com + rate_limit: 1000 + timeout: 30 + authorization_details: + description: >- + Optional authentication credentials for the connected account. Include + OAuth tokens (access_token, refresh_token, scopes) or static auth details + (API keys, bearer tokens). Can be provided later via update. + $ref: ./connected_accountsAuthorizationDetails.yaml + examples: + - oauth_token: + access_token: ya29.a0... + refresh_token: 1//0g... + scopes: + - email + - profile diff --git a/openapi/components/schemas/v1connected_accountsUpdateConnectedAccount.yaml b/openapi/components/schemas/v1connected_accountsUpdateConnectedAccount.yaml new file mode 100644 index 000000000..a8f33e212 --- /dev/null +++ b/openapi/components/schemas/v1connected_accountsUpdateConnectedAccount.yaml @@ -0,0 +1,25 @@ +type: object +title: Payload for updating an existing connected account - all fields optional +properties: + api_config: + description: >- + Updated JSON configuration for API-specific settings. Merges with existing + configuration - only provided fields are modified. + type: object + examples: + - rate_limit: 2000 + timeout: 60 + authorization_details: + description: >- + Updated authentication credentials. Provide new OAuth tokens (e.g., after + refresh) or updated static auth details. Only included fields will be + modified. + $ref: ./connected_accountsAuthorizationDetails.yaml + examples: + - oauth_token: + access_token: ya29.new_token... + refresh_token: 1//0g... + scopes: + - email + - profile + - calendar diff --git a/openapi/components/schemas/v1domainsCreateDomain.yaml b/openapi/components/schemas/v1domainsCreateDomain.yaml new file mode 100644 index 000000000..e2719d5ab --- /dev/null +++ b/openapi/components/schemas/v1domainsCreateDomain.yaml @@ -0,0 +1,22 @@ +type: object +properties: + domain: + description: >- + The domain name to be configured. Must be a valid business domain you + control. Public and disposable domains (gmail.com, outlook.com, etc.) are + automatically blocked for security. + type: string + examples: + - customerdomain.com + domain_type: + description: > + The domain type. + + - ALLOWED_EMAIL_DOMAIN: trusted domain used to suggest the organization in + the organization switcher during sign-in/sign-up. + + - ORGANIZATION_DOMAIN: SSO discovery domain used to route users to the + correct SSO provider and enforce SSO. + $ref: ./domainsDomainType.yaml + examples: + - ORGANIZATION_DOMAIN diff --git a/openapi/components/schemas/v1organizationsCreateOrganization.yaml b/openapi/components/schemas/v1organizationsCreateOrganization.yaml new file mode 100644 index 000000000..efd079f81 --- /dev/null +++ b/openapi/components/schemas/v1organizationsCreateOrganization.yaml @@ -0,0 +1,41 @@ +type: object +required: + - display_name +properties: + display_name: + description: Name of the organization. Must be between 1 and 200 characters. + type: string + examples: + - Megasoft Inc + external_id: + description: >- + Your application's unique identifier for this organization, used to link + Scalekit with your system. + type: string + examples: + - my_unique_id + logo_url: + description: >- + HTTPS URL of the organization's logo image. Maximum 2048 characters. Must + use the https scheme. + type: string + format: uri + maxLength: 2048 + pattern: ^https:// + examples: + - https://cdn.example.com/acme-logo.png + metadata: + type: object + additionalProperties: + type: string + slug: + description: >- + DNS-safe slug for dynamic redirect URI resolution (e.g. acme for + https://acme.example.com/callback). Lowercase alphanumeric and hyphens, + 1-63 chars, must start and end with alphanumeric, unique per environment. + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([a-z0-9]|-[a-z0-9])*$ + examples: + - acme diff --git a/openapi/components/schemas/v1organizationsUpdateOrganization.yaml b/openapi/components/schemas/v1organizationsUpdateOrganization.yaml new file mode 100644 index 000000000..038b6fb68 --- /dev/null +++ b/openapi/components/schemas/v1organizationsUpdateOrganization.yaml @@ -0,0 +1,47 @@ +description: For update messages ensure the indexes are same as the base model itself. +type: object +properties: + display_name: + description: >- + Name of the organization to display in the UI. Must be between 1 and 200 + characters + type: string + examples: + - Acme Corporation + external_id: + description: >- + Your application's unique identifier for this organization, used to link + Scalekit with your system + type: string + examples: + - tenant_12345 + logo_url: + description: >- + HTTPS URL of the organization's logo image. Maximum 2048 characters. Must + use the https scheme. + type: string + format: uri + maxLength: 2048 + pattern: ^https:// + examples: + - https://cdn.example.com/acme-logo.png + metadata: + description: >- + Custom key-value pairs to store with the organization. Keys must be 3-25 + characters, values must be 1-256 characters. Maximum 10 pairs allowed. + type: object + additionalProperties: + type: string + examples: + - industry: technology + slug: + description: >- + DNS-safe slug for dynamic redirect URI resolution. Lowercase alphanumeric + and hyphens, 1-63 chars, must start and end with alphanumeric, unique per + environment. + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([a-z0-9]|-[a-z0-9])*$ + examples: + - acme diff --git a/openapi/components/schemas/v1rolesCreateOrganizationRole.yaml b/openapi/components/schemas/v1rolesCreateOrganizationRole.yaml new file mode 100644 index 000000000..bad350919 --- /dev/null +++ b/openapi/components/schemas/v1rolesCreateOrganizationRole.yaml @@ -0,0 +1,32 @@ +type: object +properties: + description: + description: Description of the organization's role + type: string + examples: + - Organization Viewer Role will be used only for viewing the objects + display_name: + description: Display name of the organization's role + type: string + examples: + - Organization Viewer Role + extends: + description: Base role name for hierarchical roles + type: string + examples: + - admin_role + name: + description: Unique name of the organization's role + type: string + examples: + - org_viewer_role + permissions: + description: >- + List of permission names to assign to this role. Permissions must exist in + the current environment. + type: array + items: + type: string + examples: + - - read:users + - write:documents diff --git a/openapi/components/schemas/v1rolesCreatePermission.yaml b/openapi/components/schemas/v1rolesCreatePermission.yaml new file mode 100644 index 000000000..d530e4945 --- /dev/null +++ b/openapi/components/schemas/v1rolesCreatePermission.yaml @@ -0,0 +1,12 @@ +type: object +properties: + description: + description: Description of the permission + type: string + examples: + - Allows user to read documents from the system + name: + description: Unique name/ID of the permission + type: string + examples: + - read:documents diff --git a/openapi/components/schemas/v1rolesCreateRole.yaml b/openapi/components/schemas/v1rolesCreateRole.yaml new file mode 100644 index 000000000..0f8646e86 --- /dev/null +++ b/openapi/components/schemas/v1rolesCreateRole.yaml @@ -0,0 +1,44 @@ +type: object +properties: + description: + description: >- + Detailed description of the role's purpose, capabilities, and intended use + cases. Maximum 2000 characters. + type: string + examples: + - >- + Can create, edit, and publish content but cannot delete content or + manage user accounts + display_name: + description: >- + Human-readable display name for the role. Used in user interfaces, + reports, and user-facing communications. + type: string + examples: + - Content Editor + extends: + description: >- + Name of the base role that this role extends. Enables hierarchical role + inheritance where this role inherits all permissions from the base role. + type: string + examples: + - viewer + name: + description: >- + Unique name identifier for the role. Must be alphanumeric with + underscores, 1-64 characters. This name is used in API calls and cannot be + changed after creation. + type: string + examples: + - content_editor + permissions: + description: >- + List of permission names to assign to this role. Permissions must exist in + the current environment. Maximum 100 permissions per role. + type: array + items: + type: string + examples: + - - read:content + - write:content + - publish:content diff --git a/openapi/components/schemas/v1rolesRole.yaml b/openapi/components/schemas/v1rolesRole.yaml new file mode 100644 index 000000000..a3e7d14c7 --- /dev/null +++ b/openapi/components/schemas/v1rolesRole.yaml @@ -0,0 +1,74 @@ +type: object +properties: + default_creator: + description: Indicates if this role is the default creator role for new organizations. + type: boolean + examples: + - true + default_member: + description: Indicates if this role is the default member role for new users. + type: boolean + examples: + - true + dependent_roles_count: + description: >- + Number of roles that extend from this role (dependent roles count). + Read-only field. + type: integer + format: int32 + examples: + - 3 + description: + description: >- + Detailed description of the role's purpose and capabilities. Maximum 2000 + characters. + type: string + examples: + - Can create, edit, and publish content but cannot delete or manage users + display_name: + description: >- + Human-readable display name for the role. Used in user interfaces and + reports. + type: string + examples: + - Content Editor + extends: + description: >- + Name of the base role that this role extends. Enables hierarchical role + inheritance. + type: string + examples: + - admin_role + id: + description: Unique system-generated identifier for the role. Immutable once created. + type: string + readOnly: true + examples: + - role_1234abcd5678efgh + is_org_role: + description: Indicates if this role is an organization role. + type: boolean + examples: + - true + name: + description: >- + Unique name identifier for the role. Must be alphanumeric with + underscores, 1-100 characters. + type: string + examples: + - content_editor + permissions: + description: >- + List of permissions with role source information. Only included when + 'include' parameter is specified in the request. + type: array + items: + type: object + $ref: ./rolesRolePermission.yaml + examples: + - - description: Read Content + name: read:content + role_name: admin_role + - description: Write Content + name: write:content + role_name: editor_role diff --git a/openapi/components/schemas/v1rolesUpdateRole.yaml b/openapi/components/schemas/v1rolesUpdateRole.yaml new file mode 100644 index 000000000..f21f9d966 --- /dev/null +++ b/openapi/components/schemas/v1rolesUpdateRole.yaml @@ -0,0 +1,38 @@ +type: object +properties: + description: + description: >- + Detailed description of the role's purpose, capabilities, and intended use + cases. Maximum 2000 characters. + type: string + examples: + - >- + Can create, edit, publish, and approve content. Cannot delete content or + manage user accounts. + display_name: + description: >- + Human-readable display name for the role. Used in user interfaces, + reports, and user-facing communications. + type: string + examples: + - Senior Content Editor + extends: + description: >- + Name of the base role that this role extends. Enables hierarchical role + inheritance where this role inherits all permissions from the base role. + type: string + examples: + - content_editor + permissions: + description: >- + List of permission names to assign to this role. When provided, this + replaces all existing role-permission mappings. Permissions must exist in + the current environment. Maximum 100 permissions per role. + type: array + items: + type: string + examples: + - - read:content + - write:content + - publish:content + - approve:content diff --git a/openapi/components/schemas/v1sessionsLocation.yaml b/openapi/components/schemas/v1sessionsLocation.yaml new file mode 100644 index 000000000..82a17d175 --- /dev/null +++ b/openapi/components/schemas/v1sessionsLocation.yaml @@ -0,0 +1,38 @@ +type: object +properties: + city: + description: >- + City name where the session originated based on IP geolocation. + Approximate location derived from IP address. + type: string + examples: + - San Francisco + latitude: + description: >- + Latitude coordinate of the estimated location. Decimal format (e.g., + '37.7749'). Note: Represents IP geolocation center and may not be precise. + type: string + examples: + - '37.7749' + longitude: + description: >- + Longitude coordinate of the estimated location. Decimal format (e.g., + '-122.4194'). Note: Represents IP geolocation center and may not be + precise. + type: string + examples: + - '-122.4194' + region: + description: >- + Geographic region name derived from IP geolocation. Represents the + country-level location (e.g., 'United States', 'France'). + type: string + examples: + - United States + region_subdivision: + description: >- + Regional subdivision code or name (e.g., state abbreviation for US, + province for Canada). Two-letter ISO format when applicable. + type: string + examples: + - CA diff --git a/openapi/components/schemas/v1usersCreateMembership.yaml b/openapi/components/schemas/v1usersCreateMembership.yaml new file mode 100644 index 000000000..e64b3ba1a --- /dev/null +++ b/openapi/components/schemas/v1usersCreateMembership.yaml @@ -0,0 +1,27 @@ +type: object +properties: + inviter_email: + description: >- + Email address of the user who invited this member. Must be a valid email + address. + type: string + examples: + - john.doe@example.com + metadata: + description: >- + Custom key-value pairs for storing additional user context. Keys (3-25 + chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + roles: + description: Role to assign to the user within the organization + type: array + items: + type: object + $ref: ./commonsRole.yaml + examples: + - - name: admin diff --git a/openapi/components/schemas/v1usersUpdateMembership.yaml b/openapi/components/schemas/v1usersUpdateMembership.yaml new file mode 100644 index 000000000..a3858dfc1 --- /dev/null +++ b/openapi/components/schemas/v1usersUpdateMembership.yaml @@ -0,0 +1,20 @@ +type: object +properties: + metadata: + description: >- + Custom key-value pairs for storing additional user context. Keys (3-25 + chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + roles: + description: Role to assign to the user within the organization + type: array + items: + type: object + $ref: ./commonsRole.yaml + examples: + - - name: admin diff --git a/openapi/components/schemas/v1usersUpdateUser.yaml b/openapi/components/schemas/v1usersUpdateUser.yaml new file mode 100644 index 000000000..0c06e975c --- /dev/null +++ b/openapi/components/schemas/v1usersUpdateUser.yaml @@ -0,0 +1,24 @@ +type: object +properties: + external_id: + description: >- + Your application's unique identifier for this organization, used to link + Scalekit with your system. + type: string + examples: + - ext_12345a67b89c + metadata: + description: >- + Custom key-value pairs for storing additional user context. Keys (3-25 + chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + user_profile: + description: >- + User's personal information including name, address, and other profile + attributes. + $ref: ./usersUpdateUserProfile.yaml diff --git a/openapi/components/schemas/webauthnAllAcceptedCredentialsOptions.yaml b/openapi/components/schemas/webauthnAllAcceptedCredentialsOptions.yaml new file mode 100644 index 000000000..0476a4776 --- /dev/null +++ b/openapi/components/schemas/webauthnAllAcceptedCredentialsOptions.yaml @@ -0,0 +1,17 @@ +type: object +properties: + all_accepted_credential_ids: + description: List of credential IDs the user can authenticate with + type: array + items: + type: string + rp_id: + description: Relying Party ID for credential operations + type: string + examples: + - example.com + user_id: + description: User ID for credential verification + type: string + examples: + - user_xyz789 diff --git a/openapi/components/schemas/webauthnDeleteCredentialResponse.yaml b/openapi/components/schemas/webauthnDeleteCredentialResponse.yaml new file mode 100644 index 000000000..6c58e84eb --- /dev/null +++ b/openapi/components/schemas/webauthnDeleteCredentialResponse.yaml @@ -0,0 +1,10 @@ +type: object +properties: + success: + description: Whether the credential was successfully deleted + type: boolean + examples: + - true + unknown_credential_options: + description: Options for handling unknown credentials in client applications + $ref: ./webauthnUnknownCredentialOptions.yaml diff --git a/openapi/components/schemas/webauthnListCredentialsResponse.yaml b/openapi/components/schemas/webauthnListCredentialsResponse.yaml new file mode 100644 index 000000000..8b2549bdb --- /dev/null +++ b/openapi/components/schemas/webauthnListCredentialsResponse.yaml @@ -0,0 +1,11 @@ +type: object +properties: + all_accepted_credentials_options: + description: Options including RP ID and all accepted credential IDs for authentication + $ref: ./webauthnAllAcceptedCredentialsOptions.yaml + credentials: + description: All passkeys registered for the user + type: array + items: + type: object + $ref: ./webauthnWebAuthnCredential.yaml diff --git a/openapi/components/schemas/webauthnUnknownCredentialOptions.yaml b/openapi/components/schemas/webauthnUnknownCredentialOptions.yaml new file mode 100644 index 000000000..fa5a4866a --- /dev/null +++ b/openapi/components/schemas/webauthnUnknownCredentialOptions.yaml @@ -0,0 +1,12 @@ +type: object +properties: + credential_id: + description: The deleted credential ID + type: string + examples: + - cred_abc123 + rp_id: + description: The RP ID for this credential + type: string + examples: + - example.com diff --git a/openapi/components/schemas/webauthnUpdateCredentialResponse.yaml b/openapi/components/schemas/webauthnUpdateCredentialResponse.yaml new file mode 100644 index 000000000..76c5d5da1 --- /dev/null +++ b/openapi/components/schemas/webauthnUpdateCredentialResponse.yaml @@ -0,0 +1,5 @@ +type: object +properties: + credential: + description: The updated credential with new display name + $ref: ./webauthnWebAuthnCredential.yaml diff --git a/openapi/components/schemas/webauthnWebAuthnCredential.yaml b/openapi/components/schemas/webauthnWebAuthnCredential.yaml new file mode 100644 index 000000000..3cd332220 --- /dev/null +++ b/openapi/components/schemas/webauthnWebAuthnCredential.yaml @@ -0,0 +1,55 @@ +type: object +properties: + attestation_type: + description: 'Type of attestation: "none", "indirect", or "direct"' + type: string + examples: + - direct + authenticator: + description: Authenticator information including model and name + $ref: ./WebAuthnCredentialAuthenticator.yaml + authenticator_flags: + description: Flags indicating authenticator capabilities + $ref: ./WebAuthnCredentialAuthenticatorFlags.yaml + client_info: + description: Geographic and network information from registration + $ref: ./WebAuthnCredentialClientInfo.yaml + created_at: + description: Timestamp when the credential was created + type: string + format: date-time + examples: + - '2025-02-15T06:23:44.560000Z' + credential_id: + description: The actual credential ID bytes from the authenticator + type: string + contentEncoding: base64 + display_name: + description: Optional user-friendly name for this passkey + type: string + examples: + - My Yubikey + id: + description: Credential unique identifier + type: string + examples: + - cred_abc123 + transports: + description: Supported transports for this credential + type: array + items: + type: string + updated_at: + description: Timestamp of last update + type: string + format: date-time + examples: + - '2025-02-15T06:23:44.560000Z' + user_agent: + description: Browser and device information from registration + $ref: ./WebAuthnCredentialUserAgent.yaml + user_id: + description: User ID this credential belongs to + type: string + examples: + - user_xyz789 diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml new file mode 100644 index 000000000..f6c93e200 --- /dev/null +++ b/openapi/openapi.yaml @@ -0,0 +1,409 @@ +info: + description: "# Overview\n\nThe Scalekit API is a RESTful API that enables you to manage organizations, users, and authentication settings. All requests must use HTTPS.\nAll API requests use the following base URLs:\n\n```\nhttps://{your-subdomain}.scalekit.dev (Development)\nhttps://{your-subdomain}.scalekit.com (Production)\nhttps://auth.yourapp.com (Custom domain)\n```\n\nScalekit operates two separate environments: Development and Production. Resources cannot be moved between environments.\n\n## Quickstart\n\nThe Scalekit API uses OAuth 2.0 Client Credentials for authentication.\n\nCopy your API credentials from the Scalekit dashboard's API Config section and set them as environment variables.\n\n```sh\nSCALEKIT_ENVIRONMENT_URL=''\nSCALEKIT_CLIENT_ID=''\nSCALEKIT_CLIENT_SECRET=''\n```\n\nGetting an access token\n\n1. Get your credentials from the [Scalekit Dashboard](https://app.scalekit.com)\n2. Request an access token:\n\n```sh\ncurl https:///oauth/token \\\n -X POST \\\n -H 'Content-Type: application/x-www-form-urlencoded' \\\n -d 'client_id={client_id}' \\\n -d 'client_secret={client_secret}' \\\n -d 'grant_type=client_credentials'\n```\n\n3. Use the access token in API requests:\n\n```sh\ncurl https:///api/v1/organizations \\\n -H 'Content-Type: application/json' \\\n -H 'Authorization: Bearer {access_token}'\n```\n\nThe response includes an access token:\n\n```json\n{\n\t\"access_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6InNua181Ok4OTEyMjU2NiIsInR5cCI6IkpXVCJ9...\",\n\t\"token_type\": \"Bearer\",\n\t\"expires_in\": 86399,\n\t\"scope\": \"openid\"\n}\n```\n\n## SDKs\n\nScalekit provides official SDKs for multiple programming languages. Check the changelog at GitHub repositories for the latest updates.\n\n### Node.js\n\n```sh\nnpm install @scalekit-sdk/node\n```\n\nCreate a new Scalekit client instance after initializing the environment variables\n\n```js\nimport { Scalekit } from \"@scalekit-sdk/node\";\n\nexport let scalekit = new Scalekit(\n\tprocess.env.SCALEKIT_ENVIRONMENT_URL,\n\tprocess.env.SCALEKIT_CLIENT_ID,\n\tprocess.env.SCALEKIT_CLIENT_SECRET\n);\n```\n\n[See the Node SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-node/releases)\n\n### Python\n\n```sh\npip install scalekit-sdk-python\n```\n\nCreate a new Scalekit client instance after initializing the environment variables.\n\n```py\nfrom scalekit import ScalekitClient\nimport os\n\nscalekit_client = ScalekitClient(\n os.environ.get('SCALEKIT_ENVIRONMENT_URL'),\n os.environ.get('SCALEKIT_CLIENT_ID'),\n os.environ.get('SCALEKIT_CLIENT_SECRET')\n)\n```\n\n[See the Python SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-python/releases)\n\n### Go\n\n```sh\ngo get -u github.com/scalekit-inc/scalekit-sdk-go\n```\n\nCreate a new Scalekit client instance after initializing the environment variables.\n\n```go\npackage main\n\nimport (\n \"os\"\n \"github.com/scalekit-inc/scalekit-sdk-go\"\n)\n\nscalekitClient := scalekit.NewScalekitClient(\n os.Getenv(\"SCALEKIT_ENVIRONMENT_URL\"),\n os.Getenv(\"SCALEKIT_CLIENT_ID\"),\n os.Getenv(\"SCALEKIT_CLIENT_SECRET\"),\n)\n```\n\n[See the Go SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-go/releases)\n\n### Java\n\n```gradle\n/* Gradle users - add the following to your dependencies in build file */\nimplementation \"com.scalekit:scalekit-sdk-java:2.0.11\"\n```\n\n```xml\n\n\n com.scalekit\n scalekit-sdk-java\n 2.0.11\n\n```\n\n[See the Java SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-java/releases)\n\n### Error handling\n\nThe API uses standard HTTP status codes:\n\n| Code | Description |\n| ----------- | -------------------- |\n| 200/201 | Success |\n| 400 | Invalid request |\n| 401 | Authentication error |\n| 404 | Resource not found |\n| 429 | Rate limit exceeded |\n| 500/501/504 | Server error |\n\nError responses include detailed information:\n\n```json\n{\n\t\"code\": 16,\n\t\"message\": \"Token empty\",\n\t\"details\": [\n\t\t{\n\t\t\t\"@type\": \"type.googleapis.com/scalekit.v1.errdetails.ErrorInfo\",\n\t\t\t\"error_code\": \"UNAUTHENTICATED\"\n\t\t}\n\t]\n}\n```\n" + title: Scalekit APIs + contact: + name: Scalekit Inc + url: https://scalekit.com + email: support@scalekit.com + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0 + version: 1.0.0 + x-scalar-sdk-installation: + - lang: shell + description: >- + Set up OAuth 2.0 Client Credentials authentication to access Scalekit + APIs. Includes credential configuration, token exchange, and + authenticated API request examples. + source: > + + # 1. Obtain API Credentials + + # Get your credentials from the Scalekit dashboard + + export SCALEKIT_ENVIRONMENT_URL="https://your-org.scalekit.dev" # Your + Scalekit environment URL + + export SCALEKIT_CLIENT_ID="your_client_id" # Your + client ID + + export SCALEKIT_CLIENT_SECRET="your_client_secret" # Your + client secret + + + # 2. Exchange client credentials an OAuth 2.0 access token + + TOKEN_RESPONSE=$(curl -s -X POST + "${SCALEKIT_ENVIRONMENT_URL}/oauth/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "client_id=${SCALEKIT_CLIENT_ID}" \ + -d "client_secret=${SCALEKIT_CLIENT_SECRET}" \ + -d "grant_type=client_credentials") + + # 3. Make Authenticated API Requests + + curl -X GET "${SCALEKIT_ENVIRONMENT_URL}/api/v1/organizations" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${ACCESS_TOKEN}" \ + -H "Accept: application/json" +paths: + /api/v1/connected_accounts: + $ref: paths/api_v1_connected_accounts.yaml + /api/v1/connected_accounts/auth: + $ref: paths/api_v1_connected_accounts_auth.yaml + /api/v1/connected_accounts/details: + $ref: paths/api_v1_connected_accounts_details.yaml + /api/v1/connected_accounts/magic_link: + $ref: paths/api_v1_connected_accounts_magic_link.yaml + /api/v1/connected_accounts/user/verify: + $ref: paths/api_v1_connected_accounts_user_verify.yaml + /api/v1/connected_accounts:delete: + $ref: paths/api_v1_connected_accounts:delete.yaml + /api/v1/connected_accounts:search: + $ref: paths/api_v1_connected_accounts:search.yaml + /api/v1/connections: + $ref: paths/api_v1_connections.yaml + /api/v1/execute_tool: + $ref: paths/api_v1_execute_tool.yaml + /api/v1/invites/organizations/{organization_id}/users/{id}/resend: + $ref: >- + paths/api_v1_invites_organizations_{organization_id}_users_{id}_resend.yaml + /api/v1/memberships/organizations/{organization_id}/users/{id}: + $ref: paths/api_v1_memberships_organizations_{organization_id}_users_{id}.yaml + /api/v1/organizations: + $ref: paths/api_v1_organizations.yaml + /api/v1/organizations/{id}: + $ref: paths/api_v1_organizations_{id}.yaml + /api/v1/organizations/{id}/portal_links: + $ref: paths/api_v1_organizations_{id}_portal_links.yaml + /api/v1/organizations/{id}/settings: + $ref: paths/api_v1_organizations_{id}_settings.yaml + /api/v1/organizations/{org_id}/roles: + $ref: paths/api_v1_organizations_{org_id}_roles.yaml + /api/v1/organizations/{org_id}/roles/{role_name}: + $ref: paths/api_v1_organizations_{org_id}_roles_{role_name}.yaml + /api/v1/organizations/{org_id}/roles:set_defaults: + $ref: paths/api_v1_organizations_{org_id}_roles:set_defaults.yaml + /api/v1/organizations/{organization_id}/clients: + $ref: paths/api_v1_organizations_{organization_id}_clients.yaml + /api/v1/organizations/{organization_id}/clients/{client_id}: + $ref: paths/api_v1_organizations_{organization_id}_clients_{client_id}.yaml + /api/v1/organizations/{organization_id}/clients/{client_id}/secrets: + $ref: >- + paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets.yaml + /api/v1/organizations/{organization_id}/clients/{client_id}/secrets/{secret_id}: + $ref: >- + paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets_{secret_id}.yaml + /api/v1/organizations/{organization_id}/connections/{id}: + $ref: paths/api_v1_organizations_{organization_id}_connections_{id}.yaml + /api/v1/organizations/{organization_id}/connections/{id}:disable: + $ref: paths/api_v1_organizations_{organization_id}_connections_{id}:disable.yaml + /api/v1/organizations/{organization_id}/connections/{id}:enable: + $ref: paths/api_v1_organizations_{organization_id}_connections_{id}:enable.yaml + /api/v1/organizations/{organization_id}/directories: + $ref: paths/api_v1_organizations_{organization_id}_directories.yaml + /api/v1/organizations/{organization_id}/directories/{directory_id}/groups: + $ref: >- + paths/api_v1_organizations_{organization_id}_directories_{directory_id}_groups.yaml + /api/v1/organizations/{organization_id}/directories/{directory_id}/users: + $ref: >- + paths/api_v1_organizations_{organization_id}_directories_{directory_id}_users.yaml + /api/v1/organizations/{organization_id}/directories/{id}: + $ref: paths/api_v1_organizations_{organization_id}_directories_{id}.yaml + /api/v1/organizations/{organization_id}/directories/{id}:disable: + $ref: paths/api_v1_organizations_{organization_id}_directories_{id}:disable.yaml + /api/v1/organizations/{organization_id}/directories/{id}:enable: + $ref: paths/api_v1_organizations_{organization_id}_directories_{id}:enable.yaml + /api/v1/organizations/{organization_id}/domains: + $ref: paths/api_v1_organizations_{organization_id}_domains.yaml + /api/v1/organizations/{organization_id}/domains/{id}: + $ref: paths/api_v1_organizations_{organization_id}_domains_{id}.yaml + /api/v1/organizations/{organization_id}/session-policy: + $ref: paths/api_v1_organizations_{organization_id}_session-policy.yaml + /api/v1/organizations/{organization_id}/settings/usermanagement: + $ref: paths/api_v1_organizations_{organization_id}_settings_usermanagement.yaml + /api/v1/organizations/{organization_id}/users: + $ref: paths/api_v1_organizations_{organization_id}_users.yaml + /api/v1/organizations/{organization_id}/users/{user_id}/permissions: + $ref: >- + paths/api_v1_organizations_{organization_id}_users_{user_id}_permissions.yaml + /api/v1/organizations/{organization_id}/users/{user_id}/roles: + $ref: paths/api_v1_organizations_{organization_id}_users_{user_id}_roles.yaml + /api/v1/organizations/{organization_id}/users:search: + $ref: paths/api_v1_organizations_{organization_id}_users:search.yaml + /api/v1/organizations:external/{external_id}: + $ref: paths/api_v1_organizations:external_{external_id}.yaml + /api/v1/passwordless/email/resend: + $ref: paths/api_v1_passwordless_email_resend.yaml + /api/v1/passwordless/email/send: + $ref: paths/api_v1_passwordless_email_send.yaml + /api/v1/passwordless/email/verify: + $ref: paths/api_v1_passwordless_email_verify.yaml + /api/v1/permissions: + $ref: paths/api_v1_permissions.yaml + /api/v1/permissions/{permission_name}: + $ref: paths/api_v1_permissions_{permission_name}.yaml + /api/v1/roles: + $ref: paths/api_v1_roles.yaml + /api/v1/roles/default: + $ref: paths/api_v1_roles_default.yaml + /api/v1/roles/{role_name}: + $ref: paths/api_v1_roles_{role_name}.yaml + /api/v1/roles/{role_name}/dependents: + $ref: paths/api_v1_roles_{role_name}_dependents.yaml + /api/v1/roles/{role_name}/permissions: + $ref: paths/api_v1_roles_{role_name}_permissions.yaml + /api/v1/roles/{role_name}/permissions/{permission_name}: + $ref: paths/api_v1_roles_{role_name}_permissions_{permission_name}.yaml + /api/v1/roles/{role_name}/permissions:all: + $ref: paths/api_v1_roles_{role_name}_permissions:all.yaml + /api/v1/roles/{role_name}/users:count: + $ref: paths/api_v1_roles_{role_name}_users:count.yaml + /api/v1/roles:set_defaults: + $ref: paths/api_v1_roles:set_defaults.yaml + /api/v1/sessions/{session_id}: + $ref: paths/api_v1_sessions_{session_id}.yaml + /api/v1/sessions/{session_id}/revoke: + $ref: paths/api_v1_sessions_{session_id}_revoke.yaml + /api/v1/users: + $ref: paths/api_v1_users.yaml + /api/v1/users/{id}: + $ref: paths/api_v1_users_{id}.yaml + /api/v1/users/{user_id}/sessions: + $ref: paths/api_v1_users_{user_id}_sessions.yaml + /api/v1/users/{user_id}/sessions/revoke: + $ref: paths/api_v1_users_{user_id}_sessions_revoke.yaml + /api/v1/users:search: + $ref: paths/api_v1_users:search.yaml + /api/v1/webauthn/credentials: + $ref: paths/api_v1_webauthn_credentials.yaml + /api/v1/webauthn/credentials/{credential_id}: + $ref: paths/api_v1_webauthn_credentials_{credential_id}.yaml +tags: + - description: > + Organization represents a customer or a tenant of your product. This is + the top level entity and all resources are mapped to this Organization + object. Each organization is uniquely identified by `organization_id`. + + + + name: Organizations + - description: >- + Permission management for defining and controlling access to system + resources. Create, retrieve, update, and delete granular permissions that + represent specific actions users can perform. Permissions are the building + blocks of role-based access control (RBAC) and can be assigned to roles to + grant users the ability to perform specific operations. Use this service + to define custom permissions for your application's unique access control + requirements. + name: Permissions + - description: >- + Comprehensive user management operations including user lifecycle, + organization memberships, and invitation workflows. This service provides + endpoints for creating, retrieving, updating, and deleting user accounts + across your Scalekit environment. It supports both individual user + operations and bulk operations for user administration, including user + search, pagination, and metadata management. The service also handles user + invitations and organization membership management. + name: Users + - description: >- + Manage enterprise connections for your Scalekit environment. This service + provides endpoints for retrieving, and updating connections. + name: Connections + - description: >- + Directory management for viewing and controlling external identity + provider connections in your Scalekit environment. This service provides + endpoints for retrieving directory information, listing directories and + their contents, and enabling or disabling directory synchronization. + name: Directory + - description: >- + Role-based access control (RBAC) for defining and managing permissions in + an environment. Create and update custom roles with explicit permissions, + model role hierarchies through inheritance, view dependent roles, manage + role-permission assignments, and list roles and permissions. Also provides + a utility to count users assigned to a role. + name: Roles + - description: >- + Comprehensive session management for user authentication and + authorization. This service provides endpoints for retrieving session + details, managing user sessions across devices, revoking individual + sessions, and terminating all active sessions for a user. It supports + session auditing, device tracking, and security monitoring with detailed + session metadata including device information, IP geolocation, and + activity timestamps. + name: Sessions + - description: > + Manage organization-level domains. Scalekit supports two domain types: + + + - ORGANIZATION_DOMAIN: Used for SSO domain discovery. When a user signs in + with a matching email domain, Scalekit routes them to the organization’s + SSO provider and enforces SSO. + + - ALLOWED_EMAIL_DOMAIN: Used to mark trusted email domains for an + organization. When a user signs in or signs up with a matching domain, + Scalekit suggests the organization in the organization switcher + (authentication-method agnostic). + name: Domains + - description: >- + Endpoints for managing API client applications. API clients enable secure, + automated interactions between software systems without human + intervention. Each client is uniquely identified by a `client_id` and can + be configured with authentication settings, redirect URIs, and security + parameters. Use these endpoints to create, manage, and configure API + clients for your API clients. + name: API Auth + externalDocs: + url: https://docs.scalekit.com/m2m/overview + - description: >- + Endpoints for sending and verifying passwordless authentication emails. + These APIs allow users to authenticate without passwords by receiving a + verification code or magic link in their email. + name: Magic link & OTP + - description: Endpoints for passkey-based authentication using WebAuthn/FIDO2 standards. + name: Passkeys + - description: >- + Manage connected accounts for third-party integrations and OAuth + connections. Connected accounts represent authenticated access to external + services like Google, Notion, Slack, and other applications. + name: Connected Accounts +externalDocs: + description: Scalekit Docs + url: https://docs.scalekit.com/ +openapi: 3.1.1 +servers: + - url: https://$SCALEKIT_ENVIRONMENT_URL +components: + securitySchemes: + oauth2: + type: oauth2 + flows: + clientCredentials: + tokenUrl: https://$SCALEKIT_ENVIRONMENT_URL/oauth/token + scopes: + '': No scope required for client credentials flow +x-scalar-environments: + production: + variables: + SCALEKIT_ENVIRONMENT_URL: + default: https://$SCALEKIT_ENVIRONMENT_URL + description: yourapp.scalekit.com + staging: + variables: + SCALEKIT_ENVIRONMENT_URL: + default: https://$SCALEKIT_ENVIRONMENT_URL + description: yourapp.scalekit.dev +x-scalar-active-environment: staging +security: + - oauth2: [] +webhooks: + organization.created: + $ref: webhooks/organization.created.yaml + organization.updated: + $ref: webhooks/organization.updated.yaml + organization.deleted: + $ref: webhooks/organization.deleted.yaml + user.signup: + $ref: webhooks/user.signup.yaml + user.login: + $ref: webhooks/user.login.yaml + user.logout: + $ref: webhooks/user.logout.yaml + user.organization_invitation: + $ref: webhooks/user.organization_invitation.yaml + user.organization_membership_created: + $ref: webhooks/user.organization_membership_created.yaml + user.organization_membership_deleted: + $ref: webhooks/user.organization_membership_deleted.yaml + user.organization_membership_updated: + $ref: webhooks/user.organization_membership_updated.yaml + organization.directory_enabled: + $ref: webhooks/organization.directory_enabled.yaml + organization.directory_disabled: + $ref: webhooks/organization.directory_disabled.yaml + organization.directory.user_created: + $ref: webhooks/organization.directory.user_created.yaml + organization.directory.user_updated: + $ref: webhooks/organization.directory.user_updated.yaml + organization.directory.user_deleted: + $ref: webhooks/organization.directory.user_deleted.yaml + organization.directory.group_created: + $ref: webhooks/organization.directory.group_created.yaml + organization.directory.group_updated: + $ref: webhooks/organization.directory.group_updated.yaml + organization.directory.group_deleted: + $ref: webhooks/organization.directory.group_deleted.yaml + organization.sso_created: + $ref: webhooks/organization.sso_created.yaml + organization.sso_enabled: + $ref: webhooks/organization.sso_enabled.yaml + organization.sso_disabled: + $ref: webhooks/organization.sso_disabled.yaml + organization.sso_deleted: + $ref: webhooks/organization.sso_deleted.yaml + role.created: + $ref: webhooks/role.created.yaml + role.updated: + $ref: webhooks/role.updated.yaml + role.deleted: + $ref: webhooks/role.deleted.yaml + permission.created: + $ref: webhooks/permission.created.yaml + permission.updated: + $ref: webhooks/permission.updated.yaml + permission.deleted: + $ref: webhooks/permission.deleted.yaml + connected_account.created: + $ref: webhooks/connected_account.created.yaml + connected_account.updated: + $ref: webhooks/connected_account.updated.yaml + connected_account.deleted: + $ref: webhooks/connected_account.deleted.yaml + connected_account.magic_link_generated: + $ref: webhooks/connected_account.magic_link_generated.yaml + connected_account.oauth_tokens_fetched: + $ref: webhooks/connected_account.oauth_tokens_fetched.yaml + connected_account.token_refresh_succeeded: + $ref: webhooks/connected_account.token_refresh_succeeded.yaml + connected_account.token_refresh_failed: + $ref: webhooks/connected_account.token_refresh_failed.yaml + connected_account.oauth_succeeded: + $ref: webhooks/connected_account.oauth_succeeded.yaml diff --git a/openapi/paths/api_v1_connected_accounts.yaml b/openapi/paths/api_v1_connected_accounts.yaml new file mode 100644 index 000000000..825700f09 --- /dev/null +++ b/openapi/paths/api_v1_connected_accounts.yaml @@ -0,0 +1,182 @@ +get: + description: >- + Retrieves a paginated list of connected accounts for third-party + integrations. Filter by organization, user, connector type, provider, or + identifier. Returns OAuth tokens, API keys, and connection status for each + account. Use pagination tokens to navigate through large result sets. + tags: + - Connected Accounts + summary: List connected accounts + operationId: ConnectedAccountService_ListConnectedAccounts + parameters: + - schema: + type: string + description: >- + Filter by organization ID. Returns only connected accounts associated + with this organization. + name: organization_id + in: query + - schema: + type: string + description: >- + Filter by user ID. Returns only connected accounts associated with this + user. + name: user_id + in: query + - schema: + type: string + description: >- + Filter by connector type (e.g., 'notion', 'slack', 'google'). + Alphanumeric characters, spaces, hyphens, underscores, and colons are + allowed. + name: connector + in: query + - schema: + type: string + description: >- + Filter by account identifier. The unique identifier for the connected + account within the third-party service (e.g., email address, workspace + ID). + name: identifier + in: query + - schema: + type: string + description: >- + Filter by OAuth provider. The authentication provider name such as + 'google', 'microsoft', 'github', etc. + name: provider + in: query + - schema: + type: integer + format: int64 + description: >- + Maximum number of connected accounts to return per page. Must be between + 0 and 100. Default is typically 10. + name: page_size + in: query + - schema: + type: string + description: >- + Pagination token from a previous response. Use the next_page_token value + from ListConnectedAccountsResponse to fetch the next page. + name: page_token + in: query + - schema: + type: string + description: >- + Text search query to filter connected accounts by name, identifier, or + other searchable fields. Case-insensitive. + name: query + in: query + responses: + '200': + description: >- + Successfully retrieved the list of connected accounts with their + authentication details and status + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsListConnectedAccountsResponse.yaml + '400': + description: >- + Invalid request - occurs when query parameters are malformed or + validation fails + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} +put: + description: >- + Updates authentication credentials and configuration for an existing + connected account. Modify OAuth tokens, refresh tokens, access scopes, or + API configuration settings. Specify the account by ID, or by combination of + organization/user, connector, and identifier. Returns the updated account + with new token expiry and status information. + tags: + - Connected Accounts + summary: Update connected account credentials + operationId: ConnectedAccountService_UpdateConnectedAccount + responses: + '200': + description: >- + Connected account updated successfully with new credentials or + configuration + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsUpdateConnectedAccountResponse.yaml + '400': + description: >- + Invalid request - missing required fields, invalid authorization + details, or validation failed + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '404': + description: Connected account not found - the specified account does not exist + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsUpdateConnectedAccountRequest.yaml + required: true +post: + description: >- + Creates a new connected account with OAuth tokens or API credentials for + third-party service integration. Supply authorization details including + access tokens, refresh tokens, scopes, and optional API configuration. The + account can be scoped to an organization or user. Returns the created + account with its unique identifier and authentication status. + tags: + - Connected Accounts + summary: Create a connected account + operationId: ConnectedAccountService_CreateConnectedAccount + responses: + '201': + description: >- + Connected account created successfully with authentication credentials + stored securely + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsCreateConnectedAccountResponse.yaml + '400': + description: >- + Invalid request - missing required fields, invalid authorization + details, or validation failed + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '409': + description: Conflict - connected account with the same identifier already exists + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsCreateConnectedAccountRequest.yaml + required: true diff --git a/openapi/paths/api_v1_connected_accounts:delete.yaml b/openapi/paths/api_v1_connected_accounts:delete.yaml new file mode 100644 index 000000000..25e5f45e7 --- /dev/null +++ b/openapi/paths/api_v1_connected_accounts:delete.yaml @@ -0,0 +1,38 @@ +post: + description: >- + Permanently removes a connected account and revokes all associated + authentication credentials. Identify the account by ID, or by combination of + organization/user, connector, and identifier. This action cannot be undone. + All OAuth tokens and API keys for this account will be invalidated. + tags: + - Connected Accounts + summary: Delete a connected account + operationId: ConnectedAccountService_DeleteConnectedAccount + responses: + '200': + description: Connected account deleted successfully and all credentials revoked + content: + application/json: + schema: {} + '400': + description: Invalid request - malformed parameters or validation failed + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '404': + description: Connected account not found - the specified account does not exist + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsDeleteConnectedAccountRequest.yaml + required: true diff --git a/openapi/paths/api_v1_connected_accounts:search.yaml b/openapi/paths/api_v1_connected_accounts:search.yaml new file mode 100644 index 000000000..4bfaa205b --- /dev/null +++ b/openapi/paths/api_v1_connected_accounts:search.yaml @@ -0,0 +1,60 @@ +get: + description: >- + Search for connected accounts in your environment using a text query that + matches against identifiers, providers, or connectors. The search performs + case-insensitive matching across account details. Returns paginated results + with account status and authentication type information. + tags: + - Connected Accounts + summary: Search connected accounts + operationId: ConnectedAccountService_SearchConnectedAccounts + parameters: + - schema: + type: string + description: >- + Search term to match against connected account identifiers, providers, + or connectors. Must be at least 3 characters. Case insensitive. + name: query + in: query + - schema: + type: integer + format: int64 + description: >- + Maximum number of connected accounts to return per page. Value must be + between 1 and 30. + name: page_size + in: query + - schema: + type: string + description: >- + Token from a previous response for pagination. Provide this to retrieve + the next page of results. + name: page_token + in: query + - schema: + type: string + description: Connection ID to filter connected accounts + name: connection_id + in: query + responses: + '200': + description: >- + Successfully retrieved matching connected accounts with pagination + support + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsSearchConnectedAccountsResponse.yaml + '400': + description: >- + Invalid request - query parameter is too short (minimum 3 characters) or + validation failed + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} diff --git a/openapi/paths/api_v1_connected_accounts_auth.yaml b/openapi/paths/api_v1_connected_accounts_auth.yaml new file mode 100644 index 000000000..7f84ee2ea --- /dev/null +++ b/openapi/paths/api_v1_connected_accounts_auth.yaml @@ -0,0 +1,66 @@ +get: + description: >- + Retrieves complete authentication details for a connected account including + OAuth tokens, refresh tokens, scopes, and API configuration. Query by + account ID or by combination of organization/user, connector, and + identifier. Returns sensitive credential information - use appropriate + access controls. + tags: + - Connected Accounts + summary: Get connected account auth credentials + operationId: ConnectedAccountService_GetConnectedAccountAuth + parameters: + - schema: + type: string + description: Organization ID for the connector + name: organization_id + in: query + - schema: + type: string + description: User ID for the connector + name: user_id + in: query + - schema: + type: string + description: >- + Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric + characters, spaces, hyphens, underscores, and colons are allowed. + name: connector + in: query + - schema: + type: string + description: >- + The unique identifier for the connected account within the third-party + service (e.g., email address, user ID, workspace identifier). + name: identifier + in: query + - schema: + type: string + description: Unique identifier for the connected account + name: id + in: query + responses: + '200': + description: >- + Successfully retrieved connected account with full authentication + details + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsGetConnectedAccountByIdentifierResponse.yaml + '400': + description: Invalid request - missing required query parameters + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '404': + description: Connected account not found - no account matches the specified criteria + content: + application/json: + schema: {} diff --git a/openapi/paths/api_v1_connected_accounts_details.yaml b/openapi/paths/api_v1_connected_accounts_details.yaml new file mode 100644 index 000000000..405cbd5c3 --- /dev/null +++ b/openapi/paths/api_v1_connected_accounts_details.yaml @@ -0,0 +1,63 @@ +get: + description: >- + Returns metadata for a connected account including status, connector type, + provider, and configuration without exposing stored authorization + credentials. Look up by account ID, or by a combination of organization (or + user), connector, and external identifier. + tags: + - Connected Accounts + summary: Get connected account metadata + operationId: ConnectedAccountService_GetConnectedAccountDetails + parameters: + - schema: + type: string + description: Organization ID for the connector + name: organization_id + in: query + - schema: + type: string + description: User ID for the connector + name: user_id + in: query + - schema: + type: string + description: >- + Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric + characters, spaces, hyphens, underscores, and colons are allowed. + name: connector + in: query + - schema: + type: string + description: >- + The unique identifier for the connected account within the third-party + service (e.g., email address, user ID, workspace identifier). + name: identifier + in: query + - schema: + type: string + description: Unique identifier for the connected account + name: id + in: query + responses: + '200': + description: Successfully retrieved connected account details + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsGetConnectedAccountByIdentifierResponse.yaml + '400': + description: Invalid request - missing required query parameters + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '404': + description: Connected account not found - no account matches the specified criteria + content: + application/json: + schema: {} diff --git a/openapi/paths/api_v1_connected_accounts_magic_link.yaml b/openapi/paths/api_v1_connected_accounts_magic_link.yaml new file mode 100644 index 000000000..d232a26fb --- /dev/null +++ b/openapi/paths/api_v1_connected_accounts_magic_link.yaml @@ -0,0 +1,35 @@ +post: + description: >- + Creates a time-limited magic link for connecting or re-authorizing a + third-party account. The link directs users to the OAuth authorization flow + for the specified connector. Returns the generated link URL and expiration + timestamp. Links typically expire after a short duration for security. + tags: + - Connected Accounts + summary: Generate authentication magic link + operationId: ConnectedAccountService_GetMagicLinkForConnectedAccount + responses: + '200': + description: Magic link generated successfully with authorization URL and expiry time + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsGetMagicLinkForConnectedAccountResponse.yaml + '400': + description: Invalid request - missing required parameters or invalid connector + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsGetMagicLinkForConnectedAccountRequest.yaml + required: true diff --git a/openapi/paths/api_v1_connected_accounts_user_verify.yaml b/openapi/paths/api_v1_connected_accounts_user_verify.yaml new file mode 100644 index 000000000..fd2a56bdc --- /dev/null +++ b/openapi/paths/api_v1_connected_accounts_user_verify.yaml @@ -0,0 +1,48 @@ +post: + description: >- + Confirms the user assertion and activates the connected account after the + user completes third-party OAuth. Called by the B2B app server with + auth_request_id and identifier. Validates that the asserted identifier + matches the one stored on the auth request and promotes pending tokens to + live. + tags: + - Connected Accounts + summary: Verify connected account user + operationId: ConnectedAccountService_VerifyConnectedAccountUser + responses: + '200': + description: Verification successful; connected account is now ACTIVE + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsVerifyConnectedAccountUserResponse.yaml + '400': + description: Invalid request - missing or malformed fields + content: + application/json: + schema: {} + '401': + description: Unauthorized - invalid or missing access token + content: + application/json: + schema: {} + '403': + description: Forbidden - identifier mismatch + content: + application/json: + schema: {} + '404': + description: >- + Not found - no pending flow for the given auth_request_id or already + consumed + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: >- + ../components/schemas/connected_accountsVerifyConnectedAccountUserRequest.yaml + required: true diff --git a/openapi/paths/api_v1_connections.yaml b/openapi/paths/api_v1_connections.yaml new file mode 100644 index 000000000..1697626eb --- /dev/null +++ b/openapi/paths/api_v1_connections.yaml @@ -0,0 +1,49 @@ +get: + description: Retrieves a list of connections in the environment + tags: + - Connections + summary: List connections + operationId: ConnectionService_ListConnections + parameters: + - schema: + type: string + description: Filter connections by organization identifier + name: organization_id + in: query + - schema: + type: string + description: Filter connections by email domain associated with the organization + name: domain + in: query + - schema: + type: string + description: >- + Filter connections by status. Use 'all' to include all connections + regardless of status. Default behavior shows only active (completed and + enabled) connections + name: include + in: query + responses: + '200': + description: Successfully retrieved connections + content: + application/json: + schema: + $ref: ../components/schemas/connectionsListConnectionsResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_connections/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_connections/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_connections/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_connections/get.java diff --git a/openapi/paths/api_v1_execute_tool.yaml b/openapi/paths/api_v1_execute_tool.yaml new file mode 100644 index 000000000..30b09fbe0 --- /dev/null +++ b/openapi/paths/api_v1_execute_tool.yaml @@ -0,0 +1,52 @@ +post: + description: >- + Executes a tool action using authentication credentials from a connected + account. Specify the tool by name and provide required parameters as JSON. + The connected account can be identified by ID, or by combination of + organization/user, connector, and identifier. Returns the execution result + data and a unique execution ID for tracking. Use this endpoint to perform + actions like sending emails, creating calendar events, or managing resources + in external services. + tags: + - Connected Accounts + summary: Execute a tool using a connected account + operationId: ToolService_ExecuteTool + responses: + '200': + description: Tool executed successfully with result data and execution ID + content: + application/json: + schema: + $ref: ../components/schemas/toolsExecuteToolResponse.yaml + '400': + description: >- + Invalid request - occurs when tool name is missing, parameters are + malformed, or tool definition validation fails + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '404': + description: >- + Tool or connected account not found - occurs when the specified tool + name or connected account does not exist + content: + application/json: + schema: {} + '500': + description: >- + Tool execution failed - occurs when the external service returns an + error or the tool encounters a runtime exception + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/toolsExecuteToolRequest.yaml + required: true diff --git a/openapi/paths/api_v1_invites_organizations_{organization_id}_users_{id}_resend.yaml b/openapi/paths/api_v1_invites_organizations_{organization_id}_users_{id}_resend.yaml new file mode 100644 index 000000000..d1a124fb0 --- /dev/null +++ b/openapi/paths/api_v1_invites_organizations_{organization_id}_users_{id}_resend.yaml @@ -0,0 +1,80 @@ +patch: + description: >- + Resends an invitation email to a user who has a pending or expired + invitation in the specified organization. If the invitation has expired, a + new invitation will be automatically created and sent. If the invitation is + still valid, a reminder email will be sent instead. Use this endpoint when a + user hasn't responded to their initial invitation and you need to send them + a reminder or when the original invitation has expired. The invitation email + includes a secure magic link that allows the user to complete their account + setup and join the organization. Each resend operation increments the resent + counter. + tags: + - Users + summary: Resend user invitation email + operationId: UserService_ResendInvite + parameters: + - schema: + type: string + description: >- + Unique identifier of the organization containing the pending invitation. + Must start with 'org_' and be 1-32 characters long. + name: organization_id + in: path + required: true + - schema: + type: string + description: >- + System-generated user ID of the user who has a pending invitation. Must + start with 'usr_' and be 19-25 characters long. + name: id + in: path + required: true + responses: + '200': + description: >- + Successfully resent the invitation email. Returns the updated invitation + object with organization ID, user ID, membership status, timestamps, and + resent count. If expired, a new invitation is created; otherwise, the + existing one is resent. + content: + application/json: + schema: + $ref: ../components/schemas/usersResendInviteResponse.yaml + '400': + description: >- + Invalid request — common causes include user ID or organization ID is + invalid, full-stack authentication is disabled, user profile is missing, + invite already accepted, or missing expiry time in user management + settings. + content: + application/json: + schema: + $ref: ../components/schemas/errdetailsErrorInfo.yaml + '404': + description: >- + Resource not found — the specified user, organization, membership, or + invitation could not be found in the specified environment. Verify that + all IDs are correct and that the resources exist before attempting to + resend an invitation. + content: + application/json: + schema: + $ref: ../components/schemas/errdetailsErrorInfo.yaml + '500': + description: >- + Internal server error — an unexpected error occurred while processing + the invitation resend request. This may be due to database connectivity + issues, problems generating the secure magic link, email delivery + service failures, or transaction errors during invitation processing. + Contact support if the problem persists. + content: + application/json: + schema: + $ref: ../components/schemas/errdetailsErrorInfo.yaml + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/UserServiceResendInviteBody.yaml + required: true diff --git a/openapi/paths/api_v1_memberships_organizations_{organization_id}_users_{id}.yaml b/openapi/paths/api_v1_memberships_organizations_{organization_id}_users_{id}.yaml new file mode 100644 index 000000000..2cb2b494b --- /dev/null +++ b/openapi/paths/api_v1_memberships_organizations_{organization_id}_users_{id}.yaml @@ -0,0 +1,165 @@ +post: + description: >- + Adds an existing user to an organization and assigns them specific roles and + permissions. Use this endpoint when you want to grant an existing user + access to a particular organization. You can specify roles, metadata, and + other membership details during the invitation process. + tags: + - Users + summary: Add existing user to organization + operationId: UserService_CreateMembership + parameters: + - schema: + type: string + description: >- + Unique identifier of the target organization. Must start with 'org_' and + be 1-32 characters long. + name: organization_id + in: path + required: true + - schema: + type: string + description: System-generated user ID. Must start with 'usr_' (19-25 characters) + name: id + in: path + required: true + - schema: + type: string + description: >- + External system identifier from connected directories. Must be unique + across the system + name: external_id + in: query + - schema: + type: boolean + description: If true, sends an activation email to the user. Defaults to true. + name: send_invitation_email + in: query + responses: + '201': + description: >- + User successfully added to the organization. Returns details of the + updated membership details + content: + application/json: + schema: + $ref: ../components/schemas/usersCreateMembershipResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_memberships_organizations_{organization_id}_users_{id}/post.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_memberships_organizations_{organization_id}_users_{id}/post.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_memberships_organizations_{organization_id}_users_{id}/post.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_memberships_organizations_{organization_id}_users_{id}/post.java + requestBody: + content: + application/json: + schema: + description: Membership details to create. Required fields must be provided. + required: + - membership + $ref: ../components/schemas/v1usersCreateMembership.yaml + required: true +delete: + description: >- + Removes a user from an organization by user ID or external ID. If the user + has no memberships left and cascade is true, the user is also deleted. This + action is irreversible and may also remove related group memberships. + tags: + - Users + summary: Delete organization membership for user + operationId: UserService_DeleteMembership + parameters: + - schema: + type: string + description: >- + Unique organization identifier. Must start with 'org_' and be 1-32 + characters long + name: organization_id + in: path + required: true + - schema: + type: string + description: System-generated user ID. Must start with 'usr_' (19-25 characters) + name: id + in: path + required: true + - schema: + type: string + description: >- + External system identifier from connected directories. Must match + existing records + name: external_id + in: query + responses: + '200': + description: User successfully marked for deletion. No content returned + content: + application/json: + schema: {} + x-codeSamples: + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_memberships_organizations_{organization_id}_users_{id}/delete.py +patch: + description: >- + Updates a user's membership details within an organization by user ID or + external ID. You can update roles and membership metadata. + tags: + - Users + summary: Update organization membership for user + operationId: UserService_UpdateMembership + parameters: + - schema: + type: string + description: >- + Unique identifier of the organization containing the membership. Must + start with 'org_' and be 1-32 characters long. + name: organization_id + in: path + required: true + - schema: + type: string + description: >- + System-generated user ID. Must start with 'usr_' and be 19-25 characters + long. + name: id + in: path + required: true + - schema: + type: string + description: Your application's unique identifier for this user. + name: external_id + in: query + responses: + '200': + description: Membership updated successfully. Returns the updated user object. + content: + application/json: + schema: + $ref: ../components/schemas/usersUpdateMembershipResponse.yaml + requestBody: + content: + application/json: + schema: + description: Membership fields to update. Only specified fields will be modified. + $ref: ../components/schemas/v1usersUpdateMembership.yaml + examples: + - role: admin + required: true diff --git a/openapi/paths/api_v1_organizations.yaml b/openapi/paths/api_v1_organizations.yaml new file mode 100644 index 000000000..bd0fee94d --- /dev/null +++ b/openapi/paths/api_v1_organizations.yaml @@ -0,0 +1,105 @@ +get: + description: >- + Retrieve a paginated list of organizations within your environment. The + response includes a `page_token` that can be used to access subsequent pages + of results. + tags: + - Organizations + summary: List organizations + operationId: OrganizationService_ListOrganization + parameters: + - schema: + type: integer + format: int64 + description: >- + Maximum number of organizations to return per page. Must be between 10 + and 100 + name: page_size + in: query + - schema: + type: string + description: >- + Pagination token from the previous response. Use to retrieve the next + page of organizations + name: page_token + in: query + - schema: + type: string + description: >- + Your application's unique identifier for this organization, used to link + Scalekit with your system + name: external_id + in: query + responses: + '200': + description: Successfully retrieved the list of organizations + content: + application/json: + schema: + $ref: ../components/schemas/organizationsListOrganizationsResponse.yaml + '400': + description: Invalid page token + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_organizations/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_organizations/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_organizations/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_organizations/get.java +post: + description: >- + Creates a new organization in your environment. Use this endpoint to add a + new tenant that can be configured with various settings and metadata + tags: + - Organizations + summary: Create an organization + operationId: OrganizationService_CreateOrganization + responses: + '201': + description: >- + Returns the newly created organization with its unique identifier and + settings + content: + application/json: + schema: + $ref: ../components/schemas/organizationsCreateOrganizationResponse.yaml + x-badges: + - name: '' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_organizations/post.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_organizations/post.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_organizations/post.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_organizations/post.java + requestBody: + content: + application/json: + schema: + description: Required parameters for creating a new organization + $ref: ../components/schemas/v1organizationsCreateOrganization.yaml + description: Organization details + required: true diff --git a/openapi/paths/api_v1_organizations:external_{external_id}.yaml b/openapi/paths/api_v1_organizations:external_{external_id}.yaml new file mode 100644 index 000000000..48837f1be --- /dev/null +++ b/openapi/paths/api_v1_organizations:external_{external_id}.yaml @@ -0,0 +1,52 @@ +get: + description: >- + Retrieves organization details by external ID, including name, region, + metadata, and settings. Only provide external_id in the path. If the id + query parameter is also supplied, it silently takes precedence over + external_id due to protobuf oneof semantics, which causes the request to + fail with a 400 Bad Request ('ExternalId is required'). + tags: + - Organizations + summary: Get organization details by external Id + operationId: OrganizationService_GetOrganizationByExternalId + parameters: + - schema: + type: string + description: >- + Unique identifier that links an organization to your app's tenant. Use + this with the GetOrganizationByExternalId endpoint. Only one of id or + external_id should be provided per request. + name: external_id + in: path + required: true + - schema: + type: string + description: >- + Unique Scalekit-generated identifier for an organization. Use this with + the GetOrganization endpoint. Do not pass this parameter when calling + GetOrganizationByExternalId — use external_id instead. + name: id + in: query + responses: + '200': + description: >- + Returns the complete organization object with ID, display name, + settings, external ID and metadata + content: + application/json: + schema: + $ref: ../components/schemas/organizationsGetOrganizationResponse.yaml + '400': + description: >- + Invalid request - external ID is empty or the caller's organization + claim does not match + content: + application/json: + schema: {} + '404': + description: >- + Organization not found - no organization exists with the specified + external ID + content: + application/json: + schema: {} diff --git a/openapi/paths/api_v1_organizations_{id}.yaml b/openapi/paths/api_v1_organizations_{id}.yaml new file mode 100644 index 000000000..e8ca3cadf --- /dev/null +++ b/openapi/paths/api_v1_organizations_{id}.yaml @@ -0,0 +1,133 @@ +get: + description: >- + Retrieves organization details by Scalekit ID, including name, region, + metadata, and settings + tags: + - Organizations + summary: Get organization details + operationId: OrganizationService_GetOrganization + parameters: + - schema: + type: string + description: >- + Unique Scalekit-generated identifier for an organization. Use this with + the GetOrganization endpoint. Do not pass this parameter when calling + GetOrganizationByExternalId — use external_id instead. + name: id + in: path + required: true + responses: + '200': + description: >- + Returns the complete organization object with ID, display name, + settings, and metadata + content: + application/json: + schema: + $ref: ../components/schemas/organizationsGetOrganizationResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_organizations_{id}/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_organizations_{id}/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_organizations_{id}/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_organizations_{id}/get.java +delete: + description: >- + Remove an existing organization from the environment using its unique + identifier + tags: + - Organizations + summary: Delete an organization + operationId: OrganizationService_DeleteOrganization + parameters: + - schema: + type: string + description: >- + Unique scalekit-generated identifier that uniquely references an + organization + name: id + in: path + required: true + responses: + '200': + description: Organization successfully deleted and no longer accessible + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_organizations_{id}/delete.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_organizations_{id}/delete.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_organizations_{id}/delete.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_organizations_{id}/delete.java +patch: + description: >- + Updates an organization's display name, external ID, or metadata. Requires a + valid organization identifier. Region code cannot be modified through this + endpoint. + tags: + - Organizations + summary: Update organization details + operationId: OrganizationService_UpdateOrganization + parameters: + - schema: + type: string + description: Unique identifier of the organization to be updated + name: id + in: path + required: true + responses: + '200': + description: >- + Returns the updated organization with all current details reflected in + the response. + content: + application/json: + schema: + $ref: ../components/schemas/organizationsUpdateOrganizationResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_organizations_{id}/patch.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_organizations_{id}/patch.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_organizations_{id}/patch.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_organizations_{id}/patch.java + requestBody: + content: + application/json: + schema: + description: Organization Parameters to be updated + $ref: ../components/schemas/v1organizationsUpdateOrganization.yaml + required: true diff --git a/openapi/paths/api_v1_organizations_{id}_portal_links.yaml b/openapi/paths/api_v1_organizations_{id}_portal_links.yaml new file mode 100644 index 000000000..ee71e4f6b --- /dev/null +++ b/openapi/paths/api_v1_organizations_{id}_portal_links.yaml @@ -0,0 +1,70 @@ +put: + description: >- + Creates a single use Admin Portal URL valid for 1 minute. Once the generated + admin portal URL is accessed or rendered, a temporary session of 6 hours is + created to allow the admin to update SSO/SCIM configuration. + tags: + - Organizations + summary: Generate admin portal link + operationId: OrganizationService_GeneratePortalLink + parameters: + - schema: + type: string + description: Organization ID + name: id + in: path + required: true + - schema: + type: array + items: + enum: + - dir_sync + - sso + type: string + style: form + explode: true + description: >- + Features to enable in the admin portal link. To enable features, append + them as URL parameters: + + + - Single Sign-On: ?features=sso + + - Directory Sync: ?features=dir_sync + + - Both features: ?features=sso&features=dir_sync + + + Example URL: https://scalekit.com/portal/lnk_123?features=sso + + - dir_sync: Enables directory synchronization configuration in the portal + - sso: Enables Single Sign-On (SSO) configuration in the portal + name: features + in: query + responses: + '200': + description: >- + Admin Portal link generated successfully. Returns the portal URL and + expiration timestamp. + content: + application/json: + schema: + $ref: ../components/schemas/organizationsGeneratePortalLinkResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{id}_portal_links/put.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_organizations_{id}_portal_links/put.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_organizations_{id}_portal_links/put.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_organizations_{id}_portal_links/put.java diff --git a/openapi/paths/api_v1_organizations_{id}_settings.yaml b/openapi/paths/api_v1_organizations_{id}_settings.yaml new file mode 100644 index 000000000..4a4383ec8 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{id}_settings.yaml @@ -0,0 +1,73 @@ +patch: + description: >- + Updates configuration settings for an organization. Supports modifying SSO + configuration, directory synchronization settings, and session parameters. + Requires organization ID and the specific settings to update. + tags: + - Organizations + summary: Toggle organization settings + operationId: OrganizationService_UpdateOrganizationSettings + parameters: + - schema: + type: string + description: >- + Unique identifier of the organization to update settings. Must begin + with 'org_' prefix + name: id + in: path + required: true + responses: + '200': + description: >- + Returns the complete organization object with updated settings applied. + Contains all organization details including ID, display name, and the + modified settings. + content: + application/json: + schema: + $ref: ../components/schemas/organizationsGetOrganizationResponse.yaml + '400': + description: >- + Invalid request - occurs when the settings payload contains invalid + values or unsupported configuration + content: + application/json: + schema: {} + '404': + description: Organization not found - the specified organization ID doesn't exist + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_organizations_{id}_settings/patch.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_organizations_{id}_settings/patch.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_organizations_{id}_settings/patch.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_organizations_{id}_settings/patch.java + requestBody: + content: + application/json: + schema: + description: >- + Settings configuration to apply to the organization. Contains + feature toggles for SSO, directory synchronization, and other + organization capabilities + $ref: ../components/schemas/organizationsOrganizationSettings.yaml + examples: + - features: + - enabled: true + name: sso + - enabled: false + name: directory_sync + required: true diff --git a/openapi/paths/api_v1_organizations_{org_id}_roles.yaml b/openapi/paths/api_v1_organizations_{org_id}_roles.yaml new file mode 100644 index 000000000..c2026a2c6 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{org_id}_roles.yaml @@ -0,0 +1,106 @@ +get: + description: >- + Retrieves all environment roles and organization specific roles. Use this + endpoint to view all role definitions, including custom roles and their + configurations. You can optionally include permission details for each role + to understand their capabilities. This is useful for role management, + auditing organization access controls, or understanding the available access + levels within the organization. + tags: + - Roles + summary: List organization roles + operationId: RolesService_ListOrganizationRoles + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + - schema: + type: string + description: >- + Include additional data in the response. Valid values: 'permissions' + (direct permissions only), 'permissions:all' (includes inherited + permissions) + name: include + in: query + responses: + '200': + description: >- + Successfully retrieved list of organization roles. Returns all roles + with their metadata and optionally their permissions. + content: + application/json: + schema: + $ref: ../components/schemas/rolesListOrganizationRolesResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_organizations_{org_id}_roles/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_organizations_{org_id}_roles/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_organizations_{org_id}_roles/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_organizations_{org_id}_roles/get.java +post: + description: >- + Creates a new role within the specified organization with basic + configuration including name, display name, description, and permissions. + Use this endpoint to define custom roles that can be assigned to users + within the organization. You can create hierarchical roles by extending + existing roles and assign specific permissions to control access levels. The + role will be scoped to the organization and can be used for + organization-specific access control. + tags: + - Roles + summary: Create organization role + operationId: RolesService_CreateOrganizationRole + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + responses: + '201': + description: >- + Organization role created successfully. Returns the complete role object + with system-generated ID and timestamps. + content: + application/json: + schema: + $ref: ../components/schemas/rolesCreateOrganizationRoleResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_organizations_{org_id}_roles/post.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_organizations_{org_id}_roles/post.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_organizations_{org_id}_roles/post.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_organizations_{org_id}_roles/post.java + requestBody: + content: + application/json: + schema: + description: Organization role details + $ref: ../components/schemas/v1rolesCreateOrganizationRole.yaml + required: true diff --git a/openapi/paths/api_v1_organizations_{org_id}_roles:set_defaults.yaml b/openapi/paths/api_v1_organizations_{org_id}_roles:set_defaults.yaml new file mode 100644 index 000000000..b19ee3066 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{org_id}_roles:set_defaults.yaml @@ -0,0 +1,56 @@ +patch: + description: >- + Updates the default member role for the specified organization. Use this + endpoint to configure which role is automatically assigned to new users when + they join the organization. The system will validate that the specified role + exists and update the organization settings accordingly. This configuration + affects all new user invitations and memberships within the organization. + tags: + - Roles + summary: Set default organization roles + operationId: RolesService_UpdateDefaultOrganizationRoles + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + responses: + '200': + description: >- + Default organization roles updated successfully. Returns the updated + default member role object with complete role information. + content: + application/json: + schema: + $ref: >- + ../components/schemas/rolesUpdateDefaultOrganizationRolesResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{org_id}_roles:set_defaults/patch.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{org_id}_roles:set_defaults/patch.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{org_id}_roles:set_defaults/patch.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{org_id}_roles:set_defaults/patch.java + requestBody: + content: + application/json: + schema: + $ref: >- + ../components/schemas/RolesServiceUpdateDefaultOrganizationRolesBody.yaml + required: true diff --git a/openapi/paths/api_v1_organizations_{org_id}_roles_{role_name}.yaml b/openapi/paths/api_v1_organizations_{org_id}_roles_{role_name}.yaml new file mode 100644 index 000000000..99cc105a4 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{org_id}_roles_{role_name}.yaml @@ -0,0 +1,187 @@ +get: + description: >- + Retrieves complete information for a specific organization role including + metadata, inheritance details, and optionally permissions. Use this endpoint + to audit role configuration and understand the role's place in the + organization's role hierarchy. You can include permission details to see + what capabilities the role provides. This operation is useful for role + management, user assignment decisions, or understanding organization access + controls. + tags: + - Roles + summary: Get organization role details + operationId: RolesService_GetOrganizationRole + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + - schema: + type: string + description: Unique name of the role + name: role_name + in: path + required: true + - schema: + type: string + description: >- + Include additional data in the response. Valid values: 'permissions' + (direct permissions only), 'permissions:all' (includes inherited + permissions) + name: include + in: query + responses: + '200': + description: >- + Successfully retrieved organization role details. Returns the role + object including metadata and inheritance details. Permissions are + included only when requested via the include parameter. + content: + application/json: + schema: + $ref: ../components/schemas/rolesGetOrganizationRoleResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/get.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/get.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/get.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/get.java +put: + description: >- + Modifies an existing organization role's properties including display name, + description, permissions, and inheritance settings. Use this endpoint to + update role metadata, change permission assignments, or modify role + hierarchy within the organization. Only the fields you specify will be + updated, leaving other properties unchanged. When updating permissions, the + new list replaces all existing permissions for the role. + tags: + - Roles + summary: Update organization role + operationId: RolesService_UpdateOrganizationRole + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + - schema: + type: string + description: Unique name of the role + name: role_name + in: path + required: true + responses: + '200': + description: >- + Organization role updated successfully. Returns the modified role object + with updated timestamps. + content: + application/json: + schema: + $ref: ../components/schemas/rolesUpdateOrganizationRoleResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/put.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/put.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/put.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/put.java + requestBody: + content: + application/json: + schema: + description: Organization role details + $ref: ../components/schemas/v1rolesUpdateRole.yaml + required: true +delete: + description: >- + Permanently removes a role from the organization and optionally reassigns + users who had that role to a different role. Use this endpoint when you need + to clean up unused roles or restructure your organization's access control + system. If users are assigned to the role being deleted, you can provide a + reassign_role_name to move those users to a different role before deletion. + This action cannot be undone, so ensure no critical users depend on the role + before deletion. + tags: + - Roles + summary: Delete organization role + operationId: RolesService_DeleteOrganizationRole + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + - schema: + type: string + description: Unique name of the role + name: role_name + in: path + required: true + - schema: + type: string + description: Role name to reassign users to when deleting this role + name: reassign_role_name + in: query + responses: + '200': + description: >- + Organization role successfully deleted and users reassigned if + specified. No content returned. + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{org_id}_roles_{role_name}/delete.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{org_id}_roles_{role_name}/delete.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{org_id}_roles_{role_name}/delete.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{org_id}_roles_{role_name}/delete.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_clients.yaml b/openapi/paths/api_v1_organizations_{organization_id}_clients.yaml new file mode 100644 index 000000000..bd39ce806 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_clients.yaml @@ -0,0 +1,93 @@ +get: + description: >- + Retrieves a paginated list of API clients for a specific organization. + Returns client details including metadata, scopes, and secret information + (without exposing actual secret values). + tags: + - API Auth + summary: List organization API clients + operationId: ClientService_ListOrganizationClients + parameters: + - schema: + type: string + description: >- + Unique identifier of the organization whose clients to list. Must start + with 'org_' prefix. + name: organization_id + in: path + required: true + - schema: + type: integer + format: int64 + description: >- + Maximum number of clients to return per page + + + Maximum number of API clients to return per page. Must be between 10 and + 100 + name: page_size + in: query + - schema: + type: string + description: >- + Pagination token from the previous response + + + Pagination token from the previous response. Use to retrieve the next + page of organization clients + name: page_token + in: query + responses: + '200': + description: >- + List of organization API clients returned successfully. Each client + includes its configuration details and metadata. + content: + application/json: + schema: + $ref: ../components/schemas/clientsListOrganizationClientsResponse.yaml + x-codeSamples: + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_clients/get.py +post: + description: >- + Creates a new API client for an organization. Returns the client details and + a plain secret (available only once). + tags: + - API Auth + summary: Create organization API client + operationId: ClientService_CreateOrganizationClient + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + responses: + '201': + description: >- + API client created successfully. Returns the client ID and plain secret + (only available at creation time). The client can be configured with + scopes, audience values, and custom claims for fine-grained access + control. + content: + application/json: + schema: + $ref: ../components/schemas/clientsCreateOrganizationClientResponse.yaml + x-codeSamples: + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_clients/post.py + requestBody: + content: + application/json: + schema: + description: Details of the client to be created + $ref: ../components/schemas/clientsOrganizationClient.yaml + required: true diff --git a/openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}.yaml b/openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}.yaml new file mode 100644 index 000000000..5ba98f30a --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}.yaml @@ -0,0 +1,118 @@ +get: + description: Retrieves details of a specific API client in an organization. + tags: + - API Auth + summary: Get organization API client + operationId: ClientService_GetOrganizationClient + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the API client + name: client_id + in: path + required: true + responses: + '200': + description: >- + Returns the complete API client configuration, including all current + settings and a list of active secrets. Note that secret values are not + included in the response for security reasons. + content: + application/json: + schema: + $ref: ../components/schemas/clientsGetOrganizationClientResponse.yaml + x-codeSamples: + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/get.py +delete: + description: >- + Permanently deletes an API client from an organization. This operation + cannot be undone and will revoke all access for the client. All associated + secrets will also be invalidated. Use this endpoint to remove unused or + compromised clients. + tags: + - API Auth + summary: Delete organization API client + operationId: ClientService_DeleteOrganizationClient + parameters: + - schema: + type: string + description: >- + Unique identifier of the organization that owns the client. Must start + with 'org_' prefix. + name: organization_id + in: path + required: true + - schema: + type: string + description: >- + Unique identifier of the API client to permanently delete. Must start + with 'm2morg_' prefix. + name: client_id + in: path + required: true + responses: + '200': + description: Organization API client successfully deleted and no longer accessible + content: + application/json: + schema: {} + x-codeSamples: + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/delete.py +patch: + description: >- + Updates an existing organization API client. Only specified fields are + modified. + tags: + - API Auth + summary: Update organization API client + operationId: ClientService_UpdateOrganizationClient + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the client + name: client_id + in: path + required: true + responses: + '200': + description: >- + Returns the updated organization API client with all current details + reflected in the response, including modified scopes, audience values, + and custom claims. + content: + application/json: + schema: + $ref: ../components/schemas/clientsUpdateOrganizationClientResponse.yaml + x-codeSamples: + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}/patch.py + requestBody: + content: + application/json: + schema: + description: Updated details for the client + $ref: ../components/schemas/clientsOrganizationClient.yaml + required: true diff --git a/openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets.yaml b/openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets.yaml new file mode 100644 index 000000000..692b342e8 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets.yaml @@ -0,0 +1,38 @@ +post: + description: >- + Creates a new secret for an organization API client. Returns the plain + secret (available only once). + tags: + - API Auth + summary: Create organization API client secret + operationId: ClientService_CreateOrganizationClientSecret + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the API client + name: client_id + in: path + required: true + responses: + '201': + description: >- + Client secret created successfully. Returns the new secret ID and the + plain secret value (only available at creation time). The secret can be + used immediately for authentication. + content: + application/json: + schema: + $ref: >- + ../components/schemas/clientsCreateOrganizationClientSecretResponse.yaml + x-codeSamples: + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}_secrets/post.py diff --git a/openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets_{secret_id}.yaml b/openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets_{secret_id}.yaml new file mode 100644 index 000000000..433d2e655 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets_{secret_id}.yaml @@ -0,0 +1,39 @@ +delete: + description: >- + Permanently deletes a secret from an organization API client. This operation + cannot be undone. + tags: + - API Auth + summary: Delete organization API client secret + operationId: ClientService_DeleteOrganizationClientSecret + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the API client + name: client_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the client secret + name: secret_id + in: path + required: true + responses: + '200': + description: Client secret successfully deleted and no longer accessible + content: + application/json: + schema: {} + x-codeSamples: + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_clients_{client_id}_secrets_{secret_id}/delete.py diff --git a/openapi/paths/api_v1_organizations_{organization_id}_connections_{id}.yaml b/openapi/paths/api_v1_organizations_{organization_id}_connections_{id}.yaml new file mode 100644 index 000000000..621ea03cd --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_connections_{id}.yaml @@ -0,0 +1,104 @@ +get: + description: >- + Retrieves the complete configuration and status details for a specific + connection by its ID within an organization. Returns all connection + properties including provider settings, protocols, and current status. + tags: + - Connections + summary: Get connection details + operationId: ConnectionService_GetConnection + parameters: + - schema: + type: string + description: >- + Organization identifier (required). Specifies which organization owns + the connection you want to retrieve. + name: organization_id + in: path + required: true + - schema: + type: string + description: >- + Connection identifier (required). Specifies which specific connection to + retrieve from the organization. + name: id + in: path + required: true + responses: + '200': + description: Successfully retrieved connection details for the specified organization + content: + application/json: + schema: + $ref: ../components/schemas/connectionsGetConnectionResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}/get.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_connections_{id}/get.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_connections_{id}/get.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_connections_{id}/get.java +delete: + description: >- + Deletes an SSO connection from the specified organization by connection ID. + Use this endpoint when an identity provider integration is no longer needed + for the organization. Returns an empty response after the SSO connection is + deleted successfully. + tags: + - Connections + summary: Delete SSO connection + operationId: ConnectionService_DeleteConnection + parameters: + - schema: + type: string + description: Organization ID for the Connection. + name: organization_id + in: path + required: true + - schema: + type: string + description: Connection ID. Unique ID for the connection + name: id + in: path + required: true + responses: + '200': + description: SSO connection deleted successfully + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}/delete.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_connections_{id}/delete.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_connections_{id}/delete.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_connections_{id}/delete.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_connections_{id}:disable.yaml b/openapi/paths/api_v1_organizations_{organization_id}_connections_{id}:disable.yaml new file mode 100644 index 000000000..f51772452 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_connections_{id}:disable.yaml @@ -0,0 +1,51 @@ +patch: + description: >- + Deactivate an existing connection for the specified organization. When + disabled, users cannot authenticate using this connection. This endpoint + changes the connection state from enabled to disabled without modifying + other configuration settings + tags: + - Connections + summary: Disable SSO connection + operationId: ConnectionService_DisableConnection + parameters: + - schema: + type: string + description: Unique identifier of the organization associated with the connection + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier for the connection to be toggled + name: id + in: path + required: true + responses: + '200': + description: Connection disabled successfully + content: + application/json: + schema: + $ref: ../components/schemas/connectionsToggleConnectionResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_connections_{id}:disable/patch.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_connections_{id}:enable.yaml b/openapi/paths/api_v1_organizations_{organization_id}_connections_{id}:enable.yaml new file mode 100644 index 000000000..77cd9bc18 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_connections_{id}:enable.yaml @@ -0,0 +1,51 @@ +patch: + description: >- + Activate an existing connection for the specified organization. When + enabled, users can authenticate using this connection. This endpoint changes + the connection state from disabled to enabled without modifying other + configuration settings + tags: + - Connections + summary: Enable SSO connection + operationId: ConnectionService_EnableConnection + parameters: + - schema: + type: string + description: Unique identifier of the organization associated with the connection + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier for the connection to be toggled + name: id + in: path + required: true + responses: + '200': + description: Connection enabled successfully + content: + application/json: + schema: + $ref: ../components/schemas/connectionsToggleConnectionResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_connections_{id}:enable/patch.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_directories.yaml b/openapi/paths/api_v1_organizations_{organization_id}_directories.yaml new file mode 100644 index 000000000..44c88cd06 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_directories.yaml @@ -0,0 +1,40 @@ +get: + tags: + - Directory + summary: List organization directories + operationId: DirectoryService_ListDirectories + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + responses: + '200': + description: Successfully retrieved the list of directories for the organization + content: + application/json: + schema: + $ref: ../components/schemas/directoriesListDirectoriesResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_directories/get.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_directories/get.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_directories/get.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_directories/get.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_directories_{directory_id}_groups.yaml b/openapi/paths/api_v1_organizations_{organization_id}_directories_{directory_id}_groups.yaml new file mode 100644 index 000000000..eeea3df12 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_directories_{directory_id}_groups.yaml @@ -0,0 +1,84 @@ +get: + description: >- + Retrieves all groups from a specified directory. Use this endpoint to view + group structures from your connected identity provider. + tags: + - Directory + summary: List directory groups + operationId: DirectoryService_ListDirectoryGroups + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the directory + name: directory_id + in: path + required: true + - schema: + type: integer + format: int64 + description: >- + Number of groups to return per page. Maximum value is 30. If not + specified, defaults to 10 + name: page_size + in: query + - schema: + type: string + description: >- + Token for pagination. Use the value returned in the 'next_page_token' + field of the previous response + name: page_token + in: query + - schema: + type: string + format: date-time + description: Filter groups updated after this timestamp. Use ISO 8601 format + name: updated_after + in: query + - schema: + type: boolean + description: >- + If true, includes full group details. If false or not specified, returns + basic information only + name: include_detail + in: query + - schema: + type: boolean + description: >- + If true, returns group and its details from external provider (default: + false) + name: include_external_groups + in: query + responses: + '200': + description: Successfully retrieved the list of groups from the specified directory + content: + application/json: + schema: + $ref: ../components/schemas/directoriesListDirectoryGroupsResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_directories_{directory_id}_groups/get.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_directories_{directory_id}_users.yaml b/openapi/paths/api_v1_organizations_{organization_id}_directories_{directory_id}_users.yaml new file mode 100644 index 000000000..f1de05230 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_directories_{directory_id}_users.yaml @@ -0,0 +1,86 @@ +get: + description: >- + Retrieves a list of all users within a specified directory for an + organization. This endpoint allows you to view user accounts associated with + your connected Directory Providers. + tags: + - Directory + summary: List directory users + operationId: DirectoryService_ListDirectoryUsers + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the directory within the organization + name: directory_id + in: path + required: true + - schema: + type: integer + format: int64 + description: >- + Number of users to return per page. Maximum value is 30. If not + specified, defaults to 10 + name: page_size + in: query + - schema: + type: string + description: >- + Token for pagination. Use the value returned in the 'next_page_token' + field of the previous response to retrieve the next page of results + name: page_token + in: query + - schema: + type: boolean + description: >- + If set to true, the response will include the full user payload with all + available details. If false or not specified, only essential user + information will be returned + name: include_detail + in: query + - schema: + type: string + description: Filter users by their membership in a specific directory group + name: directory_group_id + in: query + - schema: + type: string + format: date-time + description: >- + Filter users that were updated after the specified timestamp. Use ISO + 8601 format + name: updated_after + in: query + responses: + '200': + description: Successfully retrieved the list of users from the specified directory + content: + application/json: + schema: + $ref: ../components/schemas/directoriesListDirectoryUsersResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_directories_{directory_id}_users/get.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_directories_{id}.yaml b/openapi/paths/api_v1_organizations_{organization_id}_directories_{id}.yaml new file mode 100644 index 000000000..cda14dd2c --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_directories_{id}.yaml @@ -0,0 +1,49 @@ +get: + description: >- + Retrieves detailed information about a specific directory within an + organization + tags: + - Directory + summary: Get directory details + operationId: DirectoryService_GetDirectory + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the directory + name: id + in: path + required: true + responses: + '200': + description: Successfully retrieved directory details + content: + application/json: + schema: + $ref: ../components/schemas/directoriesGetDirectoryResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}/get.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_directories_{id}/get.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_directories_{id}/get.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_directories_{id}/get.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_directories_{id}:disable.yaml b/openapi/paths/api_v1_organizations_{organization_id}_directories_{id}:disable.yaml new file mode 100644 index 000000000..144c38d47 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_directories_{id}:disable.yaml @@ -0,0 +1,54 @@ +patch: + description: >- + Stops synchronization of users and groups from a specified directory within + an organization. This operation prevents further updates from the connected + Directory provider + tags: + - Directory + summary: Disable a directory + operationId: DirectoryService_DisableDirectory + parameters: + - schema: + type: string + description: >- + A unique identifier for the organization. The value must begin with + 'org_' and be between 1 and 32 characters long + name: organization_id + in: path + required: true + - schema: + type: string + description: >- + A unique identifier for a directory within the organization. The value + must begin with 'dir_' and be between 1 and 32 characters long + name: id + in: path + required: true + responses: + '200': + description: Successfully disabled the directory + content: + application/json: + schema: + $ref: ../components/schemas/directoriesToggleDirectoryResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_directories_{id}:disable/patch.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_directories_{id}:enable.yaml b/openapi/paths/api_v1_organizations_{organization_id}_directories_{id}:enable.yaml new file mode 100644 index 000000000..3aa7ed5e5 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_directories_{id}:enable.yaml @@ -0,0 +1,53 @@ +patch: + description: >- + Activates a directory within an organization, allowing it to synchronize + users and groups with the connected Directory provider + tags: + - Directory + summary: Enable a directory + operationId: DirectoryService_EnableDirectory + parameters: + - schema: + type: string + description: >- + A unique identifier for the organization. The value must begin with + 'org_' and be between 1 and 32 characters long + name: organization_id + in: path + required: true + - schema: + type: string + description: >- + A unique identifier for a directory within the organization. The value + must begin with 'dir_' and be between 1 and 32 characters long + name: id + in: path + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: ../components/schemas/directoriesToggleDirectoryResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_directories_{id}:enable/patch.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_domains.yaml b/openapi/paths/api_v1_organizations_{organization_id}_domains.yaml new file mode 100644 index 000000000..556730def --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_domains.yaml @@ -0,0 +1,166 @@ +get: + description: >+ + Retrieves a paginated list of all domains configured for the specified + organization. + + + Domain types: + + - ALLOWED_EMAIL_DOMAIN: Trusted domains used to suggest the organization in + the organization switcher during sign-in/sign-up (auth-method agnostic). + + - ORGANIZATION_DOMAIN: SSO discovery domains used to route users to the + correct SSO provider and enforce SSO. + + tags: + - Domains + summary: List Domains + operationId: DomainService_ListDomains + parameters: + - schema: + type: string + description: >- + Scalekit-generated unique identifier for the organization. Use either + this or external_id to identify the organization. + name: organization_id + in: path + required: true + - schema: + type: string + description: >- + Optional comma-separated list of additional fields to include in the + response (e.g., 'verification_details'). + name: include + in: query + - schema: + type: integer + format: int32 + description: >- + Maximum number of domains to return per page. Default is 30, maximum is + 100. + name: page_size + in: query + - schema: + type: integer + format: int32 + description: Page number to retrieve (0-based). Use 0 for the first page. + name: page_number + in: query + - schema: + type: string + enum: + - ALLOWED_EMAIL_DOMAIN + - ORGANIZATION_DOMAIN + description: > + The domain type. + + - ALLOWED_EMAIL_DOMAIN: trusted domain used to suggest the organization + in the organization switcher during sign-in/sign-up. + + - ORGANIZATION_DOMAIN: SSO discovery domain used to route users to the + correct SSO provider and enforce SSO. + name: domain_type + in: query + responses: + '200': + description: Successfully retrieved the list of domains. + content: + application/json: + schema: + $ref: ../components/schemas/domainsListDomainResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_domains/get.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_domains/get.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_domains/get.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_domains/get.java +post: + description: >+ + Creates and associates a domain with an organization. + + + Use one of the following domain types: + + - ALLOWED_EMAIL_DOMAIN: Adds a trusted email domain for organization + suggestions in the organization switcher during sign-in/sign-up (auth-method + agnostic). + + - ORGANIZATION_DOMAIN: Enables SSO domain discovery. If a user signs in with + a matching email domain, Scalekit redirects them to the organization’s SSO + provider and enforces SSO. + + + The domain must be a valid business domain that you control. + Public/disposable domains (e.g., gmail.com) are blocked for security. + + tags: + - Domains + summary: Create Domain + operationId: DomainService_CreateDomain + parameters: + - schema: + type: string + description: >- + Scalekit-generated unique identifier for the organization. Use either + this or external_id to identify the organization. + name: organization_id + in: path + required: true + responses: + '200': + description: Successfully created the domain. + content: + application/json: + schema: + $ref: ../components/schemas/domainsCreateDomainResponse.yaml + '400': + description: >- + Invalid request — common causes invalid domain format, public or + disposable domain, or domain already exists. + content: + application/json: + schema: + $ref: ../components/schemas/errdetailsErrorInfo.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_domains/post.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_domains/post.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_domains/post.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_domains/post.java + requestBody: + content: + application/json: + schema: + description: Domain configuration including the domain name and type. + $ref: ../components/schemas/v1domainsCreateDomain.yaml + required: true diff --git a/openapi/paths/api_v1_organizations_{organization_id}_domains_{id}.yaml b/openapi/paths/api_v1_organizations_{organization_id}_domains_{id}.yaml new file mode 100644 index 000000000..63bc56952 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_domains_{id}.yaml @@ -0,0 +1,111 @@ +get: + description: >+ + Retrieves complete details for a domain including domain type, timestamps, + and configuration information. + + tags: + - Domains + summary: Get Domain + operationId: DomainService_GetDomain + parameters: + - schema: + type: string + description: >- + Scalekit-generated unique identifier for the organization. Use either + this or external_id to identify the organization. + name: organization_id + in: path + required: true + - schema: + type: string + description: Scalekit-generated unique identifier of the domain to retrieve. + name: id + in: path + required: true + responses: + '200': + description: Successfully retrieved the domain details. + content: + application/json: + schema: + $ref: ../components/schemas/domainsGetDomainResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_domains_{id}/get.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_domains_{id}/get.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_domains_{id}/get.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_domains_{id}/get.java +delete: + description: >+ + Permanently removes a domain record from an organization. + + + - Deleting an ORGANIZATION_DOMAIN disables SSO routing/enforcement for that + domain. + + - Deleting an ALLOWED_EMAIL_DOMAIN stops organization suggestions for users + with that email domain. + + tags: + - Domains + summary: Delete Domain + operationId: DomainService_DeleteDomain + parameters: + - schema: + type: string + description: >- + Scalekit-generated unique identifier for the organization. Use either + this or external_id to identify the organization. + name: organization_id + in: path + required: true + - schema: + type: string + description: >- + Scalekit-generated unique identifier of the domain to be permanently + deleted. + name: id + in: path + required: true + responses: + '200': + description: Domain successfully deleted. + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_domains_{id}/delete.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_domains_{id}/delete.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_domains_{id}/delete.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_domains_{id}/delete.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_session-policy.yaml b/openapi/paths/api_v1_organizations_{organization_id}_session-policy.yaml new file mode 100644 index 000000000..12e8d613b --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_session-policy.yaml @@ -0,0 +1,71 @@ +get: + description: >- + Retrieves the session policy for an organization. Returns + session_policy='APPLICATION' if the organization inherits the + application-level defaults, or session_policy='CUSTOM' with the configured + values if a custom policy is active. + tags: + - Organizations + summary: Get organization session policy + operationId: OrganizationService_GetOrganizationSessionPolicy + parameters: + - schema: + type: string + description: >- + The unique identifier of the organization whose session policy is being + requested. + name: organization_id + in: path + required: true + responses: + '200': + description: Session policy retrieved successfully. + content: + application/json: + schema: + $ref: >- + ../components/schemas/organizationsGetOrganizationSessionPolicyResponse.yaml + '404': + description: Organization not found. + content: + application/json: + schema: {} +patch: + description: >- + Sets a custom session policy for an organization or reverts to + application-level settings. Send session_policy='APPLICATION' to revert to + application defaults. Send session_policy='CUSTOM' with timeout values to + activate a custom policy. + tags: + - Organizations + summary: Update organization session policy + operationId: OrganizationService_UpdateOrganizationSessionPolicy + parameters: + - schema: + type: string + description: >- + The unique identifier of the organization whose session policy is being + updated. + name: organization_id + in: path + required: true + responses: + '200': + description: Session policy updated successfully. + content: + application/json: + schema: + $ref: >- + ../components/schemas/organizationsUpdateOrganizationSessionPolicyResponse.yaml + '404': + description: Organization not found. + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: >- + ../components/schemas/OrganizationServiceUpdateOrganizationSessionPolicyBody.yaml + required: true diff --git a/openapi/paths/api_v1_organizations_{organization_id}_settings_usermanagement.yaml b/openapi/paths/api_v1_organizations_{organization_id}_settings_usermanagement.yaml new file mode 100644 index 000000000..22bef1ad0 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_settings_usermanagement.yaml @@ -0,0 +1,28 @@ +patch: + description: Upsert user management settings for an organization + tags: + - Organizations + summary: Upsert organization user setting + operationId: OrganizationService_UpsertUserManagementSettings + parameters: + - schema: + type: string + description: ID of the organization. + name: organization_id + in: path + required: true + responses: + '200': + description: Returns the updated organization setting. + content: + application/json: + schema: + $ref: >- + ../components/schemas/organizationsUpsertUserManagementSettingsResponse.yaml + requestBody: + content: + application/json: + schema: + $ref: >- + ../components/schemas/OrganizationServiceUpsertUserManagementSettingsBody.yaml + required: true diff --git a/openapi/paths/api_v1_organizations_{organization_id}_users.yaml b/openapi/paths/api_v1_organizations_{organization_id}_users.yaml new file mode 100644 index 000000000..b3e174350 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_users.yaml @@ -0,0 +1,120 @@ +get: + description: >- + Retrieves a paginated list of all users who are members of the specified + organization. Use this endpoint to view all users with access to a + particular organization, including their roles, metadata, and membership + details. Supports pagination for large user lists. + tags: + - Users + summary: List organization users + operationId: UserService_ListOrganizationUsers + parameters: + - schema: + type: string + description: >- + Unique identifier of the organization for which to list users. Must + start with 'org_' and be 1-32 characters long. + name: organization_id + in: path + required: true + - schema: + type: integer + format: int64 + description: >- + Maximum number of users to return in a single response. Valid range: + 1-100. Server may return fewer users than specified. + name: page_size + in: query + - schema: + type: string + description: >- + Pagination token from a previous ListUserResponse. Used to retrieve the + next page of results. Leave empty for the first request. + name: page_token + in: query + responses: + '200': + description: Successfully retrieved the list of users in the organization + content: + application/json: + schema: + $ref: ../components/schemas/usersListOrganizationUsersResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_users/get.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_users/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_organizations_{organization_id}_users/get.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_users/get.java +post: + description: >- + Creates a new user account and immediately adds them to the specified + organization. Use this endpoint when you want to create a user and grant + them access to an organization in a single operation. You can provide user + profile information, assign roles, and configure membership metadata. The + user receives an activation email unless this feature is disabled in the + organization settings. + tags: + - Users + summary: Create new user in organization + operationId: UserService_CreateUserAndMembership + parameters: + - schema: + type: string + name: organization_id + in: path + required: true + - schema: + type: boolean + description: If true, sends an activation email to the user. Defaults to true. + name: send_invitation_email + in: query + responses: + '201': + description: >- + User created successfully. Returns the created user object, including + system-generated identifiers and timestamps + content: + application/json: + schema: + $ref: ../components/schemas/usersCreateUserAndMembershipResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_users/post.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_users/post.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_users/post.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_users/post.java + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/usersCreateUser.yaml + required: true diff --git a/openapi/paths/api_v1_organizations_{organization_id}_users:search.yaml b/openapi/paths/api_v1_organizations_{organization_id}_users:search.yaml new file mode 100644 index 000000000..1bea167fa --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_users:search.yaml @@ -0,0 +1,69 @@ +get: + description: >- + Searches for users within a specific organization by email address, user ID, + or external ID. The query must be at least 3 characters and is + case-insensitive. Scopes results strictly to the given organization. Returns + a paginated list of matching users with up to 30 results per page. Use the + next_page_token from the response to retrieve subsequent pages. + tags: + - Users + summary: Search organization users + operationId: UserService_SearchOrganizationUsers + parameters: + - schema: + type: string + description: >- + Unique identifier of the organization to search within. Must start with + 'org_' and be 1-32 characters long. + name: organization_id + in: path + required: true + - schema: + type: string + minLength: 3 + maxLength: 100 + description: >- + Search term to match against user email, IDs, or external IDs. Must be + at least 3 characters. Case insensitive. + name: query + in: query + required: true + - schema: + type: integer + format: int64 + minimum: 1 + maximum: 30 + description: >- + Maximum number of users to return per page. Value must be between 1 and + 30. + name: page_size + in: query + - schema: + type: string + description: >- + Token from a previous response for pagination. Provide this to retrieve + the next page of results. + name: page_token + in: query + responses: + '200': + description: >- + Matching users within the organization returned; includes pagination + cursors for navigating large result sets. + content: + application/json: + schema: + $ref: ../components/schemas/usersSearchOrganizationUsersResponse.yaml + '400': + description: >- + Bad Request - query must be at least 3 characters and no more than 100 + characters, and organization_id must be a valid org_ prefixed + identifier. + content: + application/json: + schema: {} + '404': + description: Not Found - organization not found. + content: + application/json: + schema: {} diff --git a/openapi/paths/api_v1_organizations_{organization_id}_users_{user_id}_permissions.yaml b/openapi/paths/api_v1_organizations_{organization_id}_users_{user_id}_permissions.yaml new file mode 100644 index 000000000..03c5a7667 --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_users_{user_id}_permissions.yaml @@ -0,0 +1,50 @@ +get: + description: >- + Retrieves all permissions a user has access to within a specific + organization. This includes permissions from direct role assignments and + inherited permissions from role hierarchy. + tags: + - Users + summary: List user permissions + operationId: UserService_ListUserPermissions + parameters: + - schema: + type: string + description: Unique identifier for the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier for the user + name: user_id + in: path + required: true + responses: + '200': + description: Successfully retrieved the list of permissions for the user + content: + application/json: + schema: + $ref: ../components/schemas/usersListUserPermissionsResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_users_{user_id}_permissions/get.java diff --git a/openapi/paths/api_v1_organizations_{organization_id}_users_{user_id}_roles.yaml b/openapi/paths/api_v1_organizations_{organization_id}_users_{user_id}_roles.yaml new file mode 100644 index 000000000..ca1fd5dcf --- /dev/null +++ b/openapi/paths/api_v1_organizations_{organization_id}_users_{user_id}_roles.yaml @@ -0,0 +1,50 @@ +get: + description: >- + Retrieves all roles assigned to a user within a specific organization. This + includes both direct role assignments and inherited roles from role + hierarchy. + tags: + - Users + summary: List user roles + operationId: UserService_ListUserRoles + parameters: + - schema: + type: string + description: Unique identifier for the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier for the user + name: user_id + in: path + required: true + responses: + '200': + description: Successfully retrieved the list of roles assigned to the user + content: + application/json: + schema: + $ref: ../components/schemas/usersListUserRolesResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_organizations_{organization_id}_users_{user_id}_roles/get.java diff --git a/openapi/paths/api_v1_passwordless_email_resend.yaml b/openapi/paths/api_v1_passwordless_email_resend.yaml new file mode 100644 index 000000000..cb0478acd --- /dev/null +++ b/openapi/paths/api_v1_passwordless_email_resend.yaml @@ -0,0 +1,40 @@ +post: + description: >- + Resend a verification email if the user didn't receive it or if the previous + code/link has expired + tags: + - Magic link & OTP + summary: Resend passwordless email + operationId: PasswordlessService_ResendPasswordlessEmail + responses: + '200': + description: >- + Successfully resent the passwordless authentication email. Returns + updated authentication request details with new expiration time. + content: + application/json: + schema: + $ref: ../components/schemas/passwordlessSendPasswordlessResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_passwordless_email_resend/post.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_passwordless_email_resend/post.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_passwordless_email_resend/post.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_passwordless_email_resend/post.java + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/passwordlessResendPasswordlessRequest.yaml + required: true diff --git a/openapi/paths/api_v1_passwordless_email_send.yaml b/openapi/paths/api_v1_passwordless_email_send.yaml new file mode 100644 index 000000000..96b53029c --- /dev/null +++ b/openapi/paths/api_v1_passwordless_email_send.yaml @@ -0,0 +1,41 @@ +post: + description: >- + Send a verification email containing either a verification code (OTP), magic + link, or both to a user's email address + tags: + - Magic link & OTP + summary: Send passwordless email + operationId: PasswordlessService_SendPasswordlessEmail + responses: + '200': + description: >- + Successfully sent passwordless authentication email. Returns the + authentication request details including expiration time and auth + request ID + content: + application/json: + schema: + $ref: ../components/schemas/passwordlessSendPasswordlessResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_passwordless_email_send/post.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_passwordless_email_send/post.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_passwordless_email_send/post.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_passwordless_email_send/post.java + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/passwordlessSendPasswordlessRequest.yaml + required: true diff --git a/openapi/paths/api_v1_passwordless_email_verify.yaml b/openapi/paths/api_v1_passwordless_email_verify.yaml new file mode 100644 index 000000000..f52cc646d --- /dev/null +++ b/openapi/paths/api_v1_passwordless_email_verify.yaml @@ -0,0 +1,40 @@ +post: + description: >- + Verify a user's identity using either a verification code or magic link + token + tags: + - Magic link & OTP + summary: Verify passwordless email + operationId: PasswordlessService_VerifyPasswordlessEmail + responses: + '200': + description: >- + Successfully verified the passwordless authentication. Returns user + email + content: + application/json: + schema: + $ref: ../components/schemas/passwordlessVerifyPasswordLessResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_passwordless_email_verify/post.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_passwordless_email_verify/post.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_passwordless_email_verify/post.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_passwordless_email_verify/post.java + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/passwordlessVerifyPasswordLessRequest.yaml + required: true diff --git a/openapi/paths/api_v1_permissions.yaml b/openapi/paths/api_v1_permissions.yaml new file mode 100644 index 000000000..caa2bead6 --- /dev/null +++ b/openapi/paths/api_v1_permissions.yaml @@ -0,0 +1,111 @@ +get: + description: >- + Retrieves a comprehensive, paginated list of all permissions available + within the environment. Use this endpoint to view all permission definitions + for auditing, role management, or understanding the complete set of + available access controls. The response includes pagination tokens to + navigate through large sets of permissions efficiently. Each permission + object contains the permission name, description, creation time, and last + update time. This operation is useful for building permission selection + interfaces, auditing permission usage, or understanding the scope of + available access controls in your RBAC system. + tags: + - Permissions + summary: List all permissions + operationId: RolesService_ListPermissions + parameters: + - schema: + type: string + description: Page token to retrieve next page of results + name: page_token + in: query + - schema: + type: integer + format: int64 + description: Number of permissions to return per page (max 100) + name: page_size + in: query + - schema: + type: string + enum: + - SCALEKIT + - ENVIRONMENT + description: >- + Filter permissions by type: ALL, SCALEKIT, or ENVIRONMENT, where + SCALEKIT are predefined Scalekit permissions and ENVIRONMENT are custom + permissions created in the environment, default is ALL + name: type + in: query + responses: + '200': + description: >- + Successfully retrieved the list of permissions. Returns a paginated list + of permission objects with metadata and pagination tokens for + navigation. + content: + application/json: + schema: + $ref: ../components/schemas/rolesListPermissionsResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_permissions/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_permissions/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_permissions/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_permissions/get.java +post: + description: >- + Creates a new permission that represents a specific action users can perform + within the environment. Use this endpoint to define granular access controls + for your RBAC system. You can provide a unique permission name following the + format 'action:resource' (for example, 'read:documents', 'write:users') and + an optional description explaining the permission's purpose. The permission + name must be unique across the environment and follows alphanumeric naming + conventions with colons and underscores. Returns the created permission + object including system-generated ID and timestamps. + tags: + - Permissions + summary: Create new permission + operationId: RolesService_CreatePermission + responses: + '201': + description: >- + Permission created successfully. Returns the complete permission object + with system-generated ID, name, description, and timestamps. + content: + application/json: + schema: + $ref: ../components/schemas/rolesCreatePermissionResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_permissions/post.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_permissions/post.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_permissions/post.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_permissions/post.java + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/v1rolesCreatePermission.yaml + required: true diff --git a/openapi/paths/api_v1_permissions_{permission_name}.yaml b/openapi/paths/api_v1_permissions_{permission_name}.yaml new file mode 100644 index 000000000..1d49ff581 --- /dev/null +++ b/openapi/paths/api_v1_permissions_{permission_name}.yaml @@ -0,0 +1,148 @@ +get: + description: >- + Retrieves complete information for a specific permission by its unique name + identifier. Use this endpoint to view permission details including + description, creation time, and last update time. Provide the permission + name in the path parameter following the format 'action:resource' (for + example, 'read:documents'). This operation is useful for auditing permission + definitions, understanding permission purposes, or verifying permission + existence before assignment. Returns the complete permission object with all + metadata and system-generated timestamps. + tags: + - Permissions + summary: Retrieve permission details + operationId: RolesService_GetPermission + parameters: + - schema: + type: string + description: Name of the permission + name: permission_name + in: path + required: true + responses: + '200': + description: >- + Successfully retrieved permission details. Returns the complete + permission object including name, description, creation time, and update + time. + content: + application/json: + schema: + $ref: ../components/schemas/rolesGetPermissionResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_permissions_{permission_name}/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_permissions_{permission_name}/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_permissions_{permission_name}/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_permissions_{permission_name}/get.java +put: + description: >- + Modifies an existing permission's attributes including description and + metadata. Use this endpoint to update permission descriptions or clarify + permission purposes after creation. The permission is identified by its + unique name in the path parameter, and only the fields you specify in the + request body will be updated. Note that the permission name itself cannot be + changed as it serves as the immutable identifier. This operation is useful + for maintaining clear documentation of permission purposes or updating + descriptions to reflect changes in system functionality. Returns the updated + permission object with modified timestamps. + tags: + - Permissions + summary: Update permission details + operationId: RolesService_UpdatePermission + parameters: + - schema: + type: string + description: Name of the permission + name: permission_name + in: path + required: true + responses: + '200': + description: >- + Permission updated successfully. Returns the modified permission object + with updated description and timestamps. + content: + application/json: + schema: + $ref: ../components/schemas/rolesUpdatePermissionResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_permissions_{permission_name}/put.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_permissions_{permission_name}/put.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_permissions_{permission_name}/put.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_permissions_{permission_name}/put.java + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/v1rolesCreatePermission.yaml + required: true +delete: + description: >- + Permanently removes a permission from the environment using its unique name + identifier. Use this endpoint when you need to clean up unused permissions + or remove access controls that are no longer relevant. The permission is + identified by its name in the path parameter following the format + 'action:resource'. This operation cannot be undone, so ensure no active + roles depend on the permission before deletion. If the permission is + currently assigned to any roles, you may need to remove those assignments + first or update the roles to use alternative permissions. Returns no content + on successful deletion. + tags: + - Permissions + summary: Delete permission + operationId: RolesService_DeletePermission + parameters: + - schema: + type: string + description: Name of the permission + name: permission_name + in: path + required: true + responses: + '200': + description: Permission successfully deleted. No content returned. + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_permissions_{permission_name}/delete.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_permissions_{permission_name}/delete.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_permissions_{permission_name}/delete.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_permissions_{permission_name}/delete.java diff --git a/openapi/paths/api_v1_roles.yaml b/openapi/paths/api_v1_roles.yaml new file mode 100644 index 000000000..f8a4e8689 --- /dev/null +++ b/openapi/paths/api_v1_roles.yaml @@ -0,0 +1,102 @@ +get: + description: >- + Retrieves a comprehensive list of all roles available within the specified + environment including organization roles. Use this endpoint to view all role + definitions, including custom roles and their configurations. You can + optionally include permission details for each role to understand their + capabilities. This is useful for role management, auditing organization + access controls, or understanding the available access levels within the + organization. + tags: + - Roles + summary: List all roles in environment + operationId: RolesService_ListRoles + parameters: + - schema: + type: string + description: >- + Include additional data in the response. Valid values: 'permissions' + (direct permissions only), 'permissions:all' (includes inherited + permissions from role hierarchy) + name: include + in: query + responses: + '200': + description: >- + Successfully retrieved list of roles. Returns all roles with their + metadata and optionally their permissions. + content: + application/json: + schema: + $ref: ../components/schemas/rolesListRolesResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_roles/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_roles/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_roles/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_roles/get.java +post: + description: >- + Creates a new role within the environment with specified permissions and + metadata. Use this endpoint to define custom roles that can be assigned to + users or groups. You can create hierarchical roles by extending existing + roles, assign specific permissions, and configure display information. Roles + are the foundation of your access control system and determine what actions + users can perform. + tags: + - Roles + summary: Create new role in environment + operationId: RolesService_CreateRole + responses: + '201': + description: >- + Role created successfully. Returns the complete role object with + system-generated ID and timestamps. + content: + application/json: + schema: + $ref: ../components/schemas/rolesCreateRoleResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_roles/post.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_roles/post.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_roles/post.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_roles/post.java + requestBody: + content: + application/json: + schema: + description: >- + Role configuration details including name, display name, + description, permissions, and inheritance settings. + $ref: ../components/schemas/v1rolesCreateRole.yaml + examples: + - description: Can edit content + display_name: Content Editor + name: content_editor + permissions: + - read:content + - write:content + required: true diff --git a/openapi/paths/api_v1_roles:set_defaults.yaml b/openapi/paths/api_v1_roles:set_defaults.yaml new file mode 100644 index 000000000..fcfd933f2 --- /dev/null +++ b/openapi/paths/api_v1_roles:set_defaults.yaml @@ -0,0 +1,43 @@ +patch: + description: >- + Updates the default creator and member roles for the current environment. + Use this endpoint to configure which roles are automatically assigned to new + users when they join the environment. You can specify role names for both + creator and member default roles. The system will validate that the + specified roles exist and update the environment settings accordingly. + Returns the updated default role objects including their complete role + information and permissions. + tags: + - Roles + summary: Set default creator and member roles + operationId: RolesService_UpdateDefaultRoles + responses: + '200': + description: Default roles updated successfully + content: + application/json: + schema: + $ref: ../components/schemas/rolesUpdateDefaultRolesResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_roles:set_defaults/patch.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_roles:set_defaults/patch.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_roles:set_defaults/patch.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_roles:set_defaults/patch.java + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/rolesUpdateDefaultRolesRequest.yaml + required: true diff --git a/openapi/paths/api_v1_roles_default.yaml b/openapi/paths/api_v1_roles_default.yaml new file mode 100644 index 000000000..622435335 --- /dev/null +++ b/openapi/paths/api_v1_roles_default.yaml @@ -0,0 +1,26 @@ +patch: + description: >- + Updates the default creator and member roles for the current environment. + Use this endpoint to configure which roles are automatically assigned to new + users when they join the environment. You can specify role names for both + creator and member default roles. The system will validate that the + specified roles exist and update the environment settings accordingly. + Returns the updated default role objects including their complete role + information and permissions. + tags: + - Roles + summary: Set default creator and member roles + operationId: RolesService_UpdateDefaultRoles2 + responses: + '200': + description: Default roles updated successfully + content: + application/json: + schema: + $ref: ../components/schemas/rolesUpdateDefaultRolesResponse.yaml + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/rolesUpdateDefaultRolesRequest.yaml + required: true diff --git a/openapi/paths/api_v1_roles_{role_name}.yaml b/openapi/paths/api_v1_roles_{role_name}.yaml new file mode 100644 index 000000000..991b7afd0 --- /dev/null +++ b/openapi/paths/api_v1_roles_{role_name}.yaml @@ -0,0 +1,166 @@ +get: + description: >- + Retrieves complete information for a specific role including metadata and + inheritance details (base role and dependent role count). Use this endpoint + to audit role configuration and understand the role's place in the + hierarchy. To view the role's permissions, use the ListRolePermissions + endpoint. + tags: + - Roles + summary: Get role details + operationId: RolesService_GetRole + parameters: + - schema: + type: string + description: >- + Unique name identifier of the role to retrieve. Must be alphanumeric + with underscores, 1-64 characters. + name: role_name + in: path + required: true + - schema: + type: string + description: >- + Include additional data in the response. Valid values: 'permissions' + (direct permissions only), 'permissions:all' (includes inherited + permissions from role hierarchy) + name: include + in: query + responses: + '200': + description: >- + Successfully retrieved role details. Returns the role object including + metadata and inheritance details. Permissions are not included. + content: + application/json: + schema: + $ref: ../components/schemas/rolesGetRoleResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_roles_{role_name}/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_roles_{role_name}/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_roles_{role_name}/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_roles_{role_name}/get.java +put: + description: >- + Modifies an existing role's properties including display name, description, + permissions, and inheritance. Use this endpoint to update role metadata, + change permission assignments, or modify role hierarchy. Only the fields you + specify will be updated, leaving other properties unchanged. When updating + permissions, the new list replaces all existing permissions for the role. + tags: + - Roles + summary: Update role information + operationId: RolesService_UpdateRole + parameters: + - schema: + type: string + description: >- + Unique name identifier of the role to update. Must be alphanumeric with + underscores, 1-64 characters. + name: role_name + in: path + required: true + responses: + '200': + description: >- + Role updated successfully. Returns the modified role object with updated + timestamps. + content: + application/json: + schema: + $ref: ../components/schemas/rolesUpdateRoleResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_roles_{role_name}/put.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_roles_{role_name}/put.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_roles_{role_name}/put.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_roles_{role_name}/put.java + requestBody: + content: + application/json: + schema: + description: Role fields to update. Only specified fields will be modified. + $ref: ../components/schemas/v1rolesUpdateRole.yaml + examples: + - description: Can edit and approve content + display_name: Senior Editor + required: true +delete: + description: >- + Permanently removes a role from the environment and reassigns users who had + that role to a different role. Use this endpoint when you need to clean up + unused roles or restructure your access control system. The role cannot be + deleted if it has dependent roles (roles that extend it) unless you specify + a replacement role. If users are assigned to the role being deleted, you + must provide a reassign_role_name to move those users to a different role + before deletion can proceed. This action cannot be undone, so ensure no + critical users depend on the role before deletion. + tags: + - Roles + summary: Delete role and reassign users + operationId: RolesService_DeleteRole + parameters: + - schema: + type: string + description: >- + Unique name identifier of the role to delete. Must be alphanumeric with + underscores, 1-64 characters. + name: role_name + in: path + required: true + - schema: + type: string + description: Role name to reassign users to when deleting this role + name: reassign_role_id + in: query + - schema: + type: string + description: Role name to reassign users to when deleting this role + name: reassign_role_name + in: query + responses: + '200': + description: Role successfully deleted and users reassigned. No content returned. + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_roles_{role_name}/delete.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_roles_{role_name}/delete.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_roles_{role_name}/delete.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_roles_{role_name}/delete.java diff --git a/openapi/paths/api_v1_roles_{role_name}_dependents.yaml b/openapi/paths/api_v1_roles_{role_name}_dependents.yaml new file mode 100644 index 000000000..007596263 --- /dev/null +++ b/openapi/paths/api_v1_roles_{role_name}_dependents.yaml @@ -0,0 +1,49 @@ +get: + description: >- + Retrieves all roles that directly extend the specified base role through + inheritance. Use this endpoint to understand the role hierarchy and identify + which roles inherit permissions from a particular base role. Provide the + base role name as a path parameter, and the response will include all + dependent roles with their metadata and permission information. This + operation is useful for auditing role inheritance relationships, + understanding the impact of changes to base roles, or managing role + hierarchies effectively. Returns a list of dependent role objects including + their names, display names, descriptions, and permission details. + tags: + - Roles + summary: List dependent roles + operationId: RolesService_ListDependentRoles + parameters: + - schema: + type: string + description: Name of the base role + name: role_name + in: path + required: true + responses: + '200': + description: >- + Successfully retrieved dependent roles. Returns a list of all roles that + extend the specified base role, including their metadata and permission + information. + content: + application/json: + schema: + $ref: ../components/schemas/rolesListDependentRolesResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_roles_{role_name}_dependents/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_roles_{role_name}_dependents/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_roles_{role_name}_dependents/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_roles_{role_name}_dependents/get.java diff --git a/openapi/paths/api_v1_roles_{role_name}_permissions.yaml b/openapi/paths/api_v1_roles_{role_name}_permissions.yaml new file mode 100644 index 000000000..5ea2242bc --- /dev/null +++ b/openapi/paths/api_v1_roles_{role_name}_permissions.yaml @@ -0,0 +1,107 @@ +get: + description: >- + Retrieves all permissions directly assigned to the specified role, excluding + permissions inherited from base roles. Use this endpoint to view the + explicit permission assignments for a role, which is useful for + understanding direct role capabilities, auditing permission assignments, or + managing role-permission relationships. Provide the role name as a path + parameter, and the response will include only the permissions that are + directly assigned to that role. This operation does not include inherited + permissions from role hierarchies - use ListEffectiveRolePermissions to see + the complete set of permissions including inheritance. Returns a list of + permission objects with their names, descriptions, and assignment metadata. + tags: + - Roles + summary: List permissions for role + operationId: RolesService_ListRolePermissions + parameters: + - schema: + type: string + description: Name of the role + name: role_name + in: path + required: true + responses: + '200': + description: >- + Successfully retrieved role permissions. Returns a list of all + permissions directly assigned to the specified role, excluding inherited + permissions. + content: + application/json: + schema: + $ref: ../components/schemas/rolesListRolePermissionsResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_roles_{role_name}_permissions/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_roles_{role_name}_permissions/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_roles_{role_name}_permissions/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_roles_{role_name}_permissions/get.java +post: + description: >- + Adds one or more permissions to the specified role while preserving existing + permission assignments. Use this endpoint to grant additional capabilities + to a role without affecting its current permission set. Provide the role + name as a path parameter and a list of permission names in the request body. + The system will validate that all specified permissions exist in the + environment and add them to the role. Existing permission assignments remain + unchanged, making this operation safe for incremental permission management. + This is useful for gradually expanding role capabilities or adding new + permissions as your system evolves. Returns the updated list of all + permissions now assigned to the role. + tags: + - Roles + summary: Add permissions to role + operationId: RolesService_AddPermissionsToRole + parameters: + - schema: + type: string + description: Name of the role + name: role_name + in: path + required: true + responses: + '200': + description: >- + Permissions added to role successfully. Returns the complete list of all + permissions now assigned to the role, including both existing and newly + added permissions. + content: + application/json: + schema: + $ref: ../components/schemas/rolesAddPermissionsToRoleResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_roles_{role_name}_permissions/post.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_roles_{role_name}_permissions/post.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_roles_{role_name}_permissions/post.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_roles_{role_name}_permissions/post.java + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/RolesServiceAddPermissionsToRoleBody.yaml + required: true diff --git a/openapi/paths/api_v1_roles_{role_name}_permissions:all.yaml b/openapi/paths/api_v1_roles_{role_name}_permissions:all.yaml new file mode 100644 index 000000000..715e98bf8 --- /dev/null +++ b/openapi/paths/api_v1_roles_{role_name}_permissions:all.yaml @@ -0,0 +1,34 @@ +get: + description: >- + Retrieves the complete set of effective permissions for a role, including + both directly assigned permissions and permissions inherited from base roles + through the role hierarchy. Use this endpoint to understand the full scope + of capabilities available to users assigned to a specific role. Provide the + role name as a path parameter, and the response will include all permissions + that apply to the role, accounting for inheritance relationships. This + operation is essential for auditing role capabilities, understanding + permission inheritance, or verifying the complete access scope before role + assignment. Returns a comprehensive list of permission names representing + the full set of effective permissions for the specified role. + tags: + - Roles + summary: List effective permissions for role + operationId: RolesService_ListEffectiveRolePermissions + parameters: + - schema: + type: string + description: Name of the role + name: role_name + in: path + required: true + responses: + '200': + description: >- + Successfully retrieved effective permissions. Returns the complete list + of all permissions that apply to the role, including both direct + assignments and inherited permissions from base roles. + content: + application/json: + schema: + $ref: >- + ../components/schemas/rolesListEffectiveRolePermissionsResponse.yaml diff --git a/openapi/paths/api_v1_roles_{role_name}_permissions_{permission_name}.yaml b/openapi/paths/api_v1_roles_{role_name}_permissions_{permission_name}.yaml new file mode 100644 index 000000000..9c8d07af1 --- /dev/null +++ b/openapi/paths/api_v1_roles_{role_name}_permissions_{permission_name}.yaml @@ -0,0 +1,56 @@ +delete: + description: >- + Removes a specific permission from the specified role, revoking that + capability from all users assigned to the role. Use this endpoint to + restrict role capabilities or remove unnecessary permissions. Provide both + the role name and permission name as path parameters. This operation only + affects the direct permission assignment and does not impact permissions + inherited from base roles. If the permission is inherited through role + hierarchy, you may need to modify the base role instead. This is useful for + fine-tuning role permissions, implementing least-privilege access controls, + or removing deprecated permissions. Returns no content on successful + removal. + tags: + - Roles + summary: Remove permission from role + operationId: RolesService_RemovePermissionFromRole + parameters: + - schema: + type: string + description: Name of the role + name: role_name + in: path + required: true + - schema: + type: string + description: Name of the permission to remove + name: permission_name + in: path + required: true + responses: + '200': + description: Permission removed from role successfully. No content returned. + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_roles_{role_name}_permissions_{permission_name}/delete.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_roles_{role_name}_permissions_{permission_name}/delete.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_roles_{role_name}_permissions_{permission_name}/delete.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_roles_{role_name}_permissions_{permission_name}/delete.java diff --git a/openapi/paths/api_v1_roles_{role_name}_users:count.yaml b/openapi/paths/api_v1_roles_{role_name}_users:count.yaml new file mode 100644 index 000000000..f872e0793 --- /dev/null +++ b/openapi/paths/api_v1_roles_{role_name}_users:count.yaml @@ -0,0 +1,49 @@ +get: + description: >- + Retrieves the total number of users currently assigned to the specified role + within the environment. Use this endpoint to monitor role usage, enforce + user limits, or understand the scope of role assignments. Provide the role's + unique name as a path parameter, and the response will include the current + user count for that role. This operation is read-only and does not modify + any data or user assignments. The count reflects all users who have the role + either directly assigned or inherited through organization membership. This + information is useful for capacity planning, security auditing, or + understanding the impact of role changes across your user base. + tags: + - Roles + summary: Retrieve user count for role + operationId: RolesService_GetRoleUsersCount + parameters: + - schema: + type: string + description: Unique name of the role + name: role_name + in: path + required: true + responses: + '200': + description: >- + Successfully retrieved user count for the specified role. Returns the + total number of users currently assigned to the role, including both + direct assignments and inherited assignments. + content: + application/json: + schema: + $ref: ../components/schemas/rolesGetRoleUsersCountResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_roles_{role_name}_users:count/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_roles_{role_name}_users:count/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_roles_{role_name}_users:count/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_roles_{role_name}_users:count/get.java diff --git a/openapi/paths/api_v1_sessions_{session_id}.yaml b/openapi/paths/api_v1_sessions_{session_id}.yaml new file mode 100644 index 000000000..2390e1a12 --- /dev/null +++ b/openapi/paths/api_v1_sessions_{session_id}.yaml @@ -0,0 +1,46 @@ +get: + description: >- + Retrieves comprehensive details for a specific user session including + authentication status, device information, and expiration timelines. Use + this endpoint to fetch current session metadata for security audits, session + validation, or to display session information in user account management + interfaces. Returns all session properties including the user ID, + authenticated organizations, device details with browser/OS information, IP + address and geolocation, and all relevant timestamps (creation, last + activity, idle expiration, absolute expiration, and actual expiration if + applicable). + tags: + - Sessions + summary: Get session details + operationId: SessionService_GetSession + parameters: + - schema: + type: string + description: Unique identifier for the session. Must start with 'ses_' prefix. + name: session_id + in: path + required: true + responses: + '200': + description: Successfully retrieved session details + content: + application/json: + schema: + $ref: ../components/schemas/sessionsSessionDetails.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_sessions_{session_id}/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_sessions_{session_id}/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_sessions_{session_id}/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_sessions_{session_id}/get.java diff --git a/openapi/paths/api_v1_sessions_{session_id}_revoke.yaml b/openapi/paths/api_v1_sessions_{session_id}_revoke.yaml new file mode 100644 index 000000000..b587aad4f --- /dev/null +++ b/openapi/paths/api_v1_sessions_{session_id}_revoke.yaml @@ -0,0 +1,46 @@ +post: + description: >- + Immediately invalidates a specific user session by session ID, setting its + status to 'revoked'. Once revoked, the session cannot be used for any future + API requests or application access. Use this endpoint to implement + session-level logout, force a user to reauthenticate on a specific device, + or terminate suspicious sessions. The revocation is instantaneous and + irreversible. Returns the revoked session details including the session ID, + user ID, and the revocation timestamp. + tags: + - Sessions + summary: Revoke user session + operationId: SessionService_RevokeSession + parameters: + - schema: + type: string + description: >- + Unique identifier for the session to revoke. Must start with 'ses_' + prefix. + name: session_id + in: path + required: true + responses: + '200': + description: Successfully revoked the session. Returns the revoked session details + content: + application/json: + schema: + $ref: ../components/schemas/sessionsRevokeSessionResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_sessions_{session_id}_revoke/post.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_sessions_{session_id}_revoke/post.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_sessions_{session_id}_revoke/post.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_sessions_{session_id}_revoke/post.java diff --git a/openapi/paths/api_v1_users.yaml b/openapi/paths/api_v1_users.yaml new file mode 100644 index 000000000..f75c0be24 --- /dev/null +++ b/openapi/paths/api_v1_users.yaml @@ -0,0 +1,51 @@ +get: + description: >- + Retrieves a paginated list of all users across your entire environment. Use + this endpoint to view all users regardless of their organization + memberships. This is useful for administrative purposes, user audits, or + when you need to see all users in your Scalekit environment. Supports + pagination for large user bases. + tags: + - Users + summary: List all users in environment + operationId: UserService_ListUsers + parameters: + - schema: + type: integer + format: int64 + description: >- + Maximum number of organizations to return per page. Must be between 10 + and 100 + name: page_size + in: query + - schema: + type: string + description: >- + Pagination token from the previous response. Use to retrieve the next + page of organizations + name: page_token + in: query + responses: + '200': + description: List of users. + content: + application/json: + schema: + $ref: ../components/schemas/usersListUsersResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_users/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_users/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_users/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_users/get.java diff --git a/openapi/paths/api_v1_users:search.yaml b/openapi/paths/api_v1_users:search.yaml new file mode 100644 index 000000000..3bc4e3c4b --- /dev/null +++ b/openapi/paths/api_v1_users:search.yaml @@ -0,0 +1,55 @@ +get: + description: >- + Searches for users across the entire environment by email address, user ID, + or external ID. The query must be at least 3 characters and is + case-insensitive. Returns a paginated list of matching users with up to 30 + results per page. Use the next_page_token from the response to retrieve + subsequent pages. + tags: + - Users + summary: Search users + operationId: UserService_SearchUsers + parameters: + - schema: + type: string + minLength: 3 + maxLength: 100 + description: >- + Search term to match against user email, IDs, or external IDs. Must be + at least 3 characters. Case insensitive. + name: query + in: query + required: true + - schema: + type: integer + format: int64 + minimum: 1 + maximum: 30 + description: >- + Maximum number of users to return per page. Value must be between 1 and + 30. + name: page_size + in: query + - schema: + type: string + description: >- + Token from a previous response for pagination. Provide this to retrieve + the next page of results. + name: page_token + in: query + responses: + '200': + description: >- + Matching users returned; includes pagination cursors for navigating + large result sets. + content: + application/json: + schema: + $ref: ../components/schemas/usersSearchUsersResponse.yaml + '400': + description: >- + Bad Request - query must be at least 3 characters and no more than 100 + characters. + content: + application/json: + schema: {} diff --git a/openapi/paths/api_v1_users_{id}.yaml b/openapi/paths/api_v1_users_{id}.yaml new file mode 100644 index 000000000..fce69d74e --- /dev/null +++ b/openapi/paths/api_v1_users_{id}.yaml @@ -0,0 +1,161 @@ +get: + description: >- + Retrieves all details for a user by system-generated user ID or external ID. + The response includes organization memberships and user metadata. + tags: + - Users + summary: Get user + operationId: UserService_GetUser + parameters: + - schema: + type: string + description: System-generated user ID + name: id + in: path + required: true + - schema: + type: string + description: >- + Your application's unique identifier for this organization, used to link + Scalekit with your system. + name: external_id + in: query + responses: + '200': + description: >- + User details retrieved successfully. Returns full user object with + system-generated fields and timestamps. + content: + application/json: + schema: + $ref: ../components/schemas/usersGetUserResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_users_{id}/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_users_{id}/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_users_{id}/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_users_{id}/get.java +delete: + description: >- + Permanently removes a user from your environment and deletes all associated + data. Use this endpoint when you need to completely remove a user account. + This action deletes the user's profile, memberships, and all related data + across all organizations. This operation cannot be undone, so use with + caution. + tags: + - Users + summary: Delete user permanently + operationId: UserService_DeleteUser + parameters: + - schema: + type: string + description: System-generated user ID. Must start with 'usr_' (19-25 characters) + name: id + in: path + required: true + - schema: + type: string + description: >- + External system identifier from connected directories. Must match + existing records + name: external_id + in: query + responses: + '200': + description: User successfully deleted. No content returned + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_users_{id}/delete.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_users_{id}/delete.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_users_{id}/delete.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_users_{id}/delete.java +patch: + description: >- + Modifies user account information including profile details, metadata, and + external ID. Use this endpoint to update a user's personal information, + contact details, or custom metadata. You can update the user's profile, + phone number, and metadata fields. Note that fields like user ID, email + address, environment ID, and creation time cannot be modified. + tags: + - Users + summary: Update user information + operationId: UserService_UpdateUser + parameters: + - schema: + type: string + description: >- + System-generated user ID. Must start with 'usr_' and be 19-25 characters + long. + name: id + in: path + required: true + - schema: + type: string + description: >- + Your application's unique identifier for this organization, used to link + Scalekit with your system. + name: external_id + in: query + responses: + '200': + description: >- + User updated successfully. Returns the modified user object with updated + timestamps. + content: + application/json: + schema: + $ref: ../components/schemas/usersUpdateUserResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_users_{id}/patch.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_users_{id}/patch.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_users_{id}/patch.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_users_{id}/patch.java + requestBody: + content: + application/json: + schema: + description: >- + User fields to update. Only specified fields will be modified. + Required fields must be provided if being changed. + $ref: ../components/schemas/v1usersUpdateUser.yaml + examples: + - firstName: John + lastName: Doe + required: true diff --git a/openapi/paths/api_v1_users_{user_id}_sessions.yaml b/openapi/paths/api_v1_users_{user_id}_sessions.yaml new file mode 100644 index 000000000..1633611f9 --- /dev/null +++ b/openapi/paths/api_v1_users_{user_id}_sessions.yaml @@ -0,0 +1,97 @@ +get: + description: >- + Retrieves a paginated list of all sessions associated with a specific user + across all devices and browsers. Use this endpoint to audit user activity, + display all active sessions in account management interfaces, or verify user + authentication status across devices. Supports filtering by session status + (active, expired, revoked, logout) and time range (creation date). Returns + session details for each session including device information, IP address, + geolocation, and current status. The response includes pagination metadata + (page tokens and total count) to handle large session lists efficiently. + tags: + - Sessions + summary: List user sessions + operationId: SessionService_GetUserSessions + parameters: + - schema: + type: string + description: >- + Unique identifier for the user whose sessions to retrieve. Must start + with 'usr_' prefix. + name: user_id + in: path + required: true + - schema: + type: integer + format: int64 + description: >- + Maximum number of sessions to return in a single page. Optional + parameter. If not specified, defaults to a server-defined limit. Use + smaller values for faster responses, larger values for fewer requests. + name: page_size + in: query + - schema: + type: string + description: >- + Pagination token from the previous response for retrieving the next page + of results. Leave empty for the first page. Use the next_page_token from + a previous response to fetch subsequent pages. + name: page_token + in: query + - schema: + type: array + items: + type: string + style: form + explode: true + description: >- + Filter sessions by one or more status values. Possible values: 'active', + 'expired', 'revoked', 'logout'. Leave empty to include all statuses. + Multiple values use OR logic (e.g., status=['active', 'expired'] returns + sessions that are either active OR expired). + name: filter.status + in: query + - schema: + type: string + format: date-time + description: >- + Filter to include only sessions created on or after this timestamp. + Optional. Uses RFC 3339 format. Useful for querying sessions within a + specific time window. + name: filter.start_time + in: query + - schema: + type: string + format: date-time + description: >- + Filter to include only sessions created on or before this timestamp. + Optional. Uses RFC 3339 format. Must be after start_time if both are + specified. + name: filter.end_time + in: query + responses: + '200': + description: >- + Successfully retrieved user sessions. Returns a list of sessions with + pagination information + content: + application/json: + schema: + $ref: ../components/schemas/sessionsUserSessionDetails.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_users_{user_id}_sessions/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_users_{user_id}_sessions/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_users_{user_id}_sessions/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_users_{user_id}_sessions/get.java diff --git a/openapi/paths/api_v1_users_{user_id}_sessions_revoke.yaml b/openapi/paths/api_v1_users_{user_id}_sessions_revoke.yaml new file mode 100644 index 000000000..51420519f --- /dev/null +++ b/openapi/paths/api_v1_users_{user_id}_sessions_revoke.yaml @@ -0,0 +1,50 @@ +post: + description: >- + Immediately invalidates all active sessions for a specific user across all + devices and browsers, setting their status to 'revoked'. Use this endpoint + to implement global logout functionality, force re-authentication after + security incidents, or terminate all sessions following a password reset or + credential compromise. Only active sessions are revoked; already expired, + logout, or previously revoked sessions remain unchanged. The revocation is + atomic and instantaneous. Returns a list of all revoked sessions with their + details and a total count of sessions revoked. + tags: + - Sessions + summary: Revoke all user sessions + operationId: SessionService_RevokeAllUserSessions + parameters: + - schema: + type: string + description: >- + Unique identifier for the user whose all sessions will be revoked. Must + start with 'usr_' prefix. + name: user_id + in: path + required: true + responses: + '200': + description: >- + Successfully revoked all user sessions. Returns the list of revoked + sessions and total count + content: + application/json: + schema: + $ref: ../components/schemas/sessionsRevokeAllUserSessionsResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_users_{user_id}_sessions_revoke/post.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_users_{user_id}_sessions_revoke/post.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_users_{user_id}_sessions_revoke/post.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_users_{user_id}_sessions_revoke/post.java diff --git a/openapi/paths/api_v1_webauthn_credentials.yaml b/openapi/paths/api_v1_webauthn_credentials.yaml new file mode 100644 index 000000000..e6e57974f --- /dev/null +++ b/openapi/paths/api_v1_webauthn_credentials.yaml @@ -0,0 +1,39 @@ +get: + description: >- + Retrieves all registered passkeys for the current user, including device + information, creation timestamps, and display names. Use this to show users + their registered authenticators. + tags: + - Passkeys + summary: List user's passkeys + operationId: WebAuthnService_ListCredentials + parameters: + - schema: + type: string + description: User ID to list credentials for (optional, current user if not provided) + name: user_id + in: query + responses: + '200': + description: List of passkeys with metadata + content: + application/json: + schema: + $ref: ../components/schemas/webauthnListCredentialsResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: ../code_samples/javascript/api_v1_webauthn_credentials/get.js + - label: Python SDK + lang: python + source: + $ref: ../code_samples/python/api_v1_webauthn_credentials/get.py + - label: Go SDK + lang: go + source: + $ref: ../code_samples/go/api_v1_webauthn_credentials/get.go + - label: Java SDK + lang: java + source: + $ref: ../code_samples/java/api_v1_webauthn_credentials/get.java diff --git a/openapi/paths/api_v1_webauthn_credentials_{credential_id}.yaml b/openapi/paths/api_v1_webauthn_credentials_{credential_id}.yaml new file mode 100644 index 000000000..3dab9075f --- /dev/null +++ b/openapi/paths/api_v1_webauthn_credentials_{credential_id}.yaml @@ -0,0 +1,92 @@ +delete: + description: >- + Deletes a specific passkey credential for the current user. After removal, + the authenticator can no longer be used for authentication. + tags: + - Passkeys + summary: Remove a passkey + operationId: WebAuthnService_DeleteCredential + parameters: + - schema: + type: string + description: The credential ID to delete + name: credential_id + in: path + required: true + responses: + '200': + description: Passkey successfully deleted + content: + application/json: + schema: + $ref: ../components/schemas/webauthnDeleteCredentialResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_webauthn_credentials_{credential_id}/delete.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_webauthn_credentials_{credential_id}/delete.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_webauthn_credentials_{credential_id}/delete.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_webauthn_credentials_{credential_id}/delete.java +patch: + description: >- + Updates the display name of a passkey credential to help users identify + their authenticators. Only the display name can be modified. + tags: + - Passkeys + summary: Rename a passkey + operationId: WebAuthnService_UpdateCredential + parameters: + - schema: + type: string + description: The credential ID to update + name: credential_id + in: path + required: true + responses: + '200': + description: Passkey successfully updated with new name + content: + application/json: + schema: + $ref: ../components/schemas/webauthnUpdateCredentialResponse.yaml + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: + $ref: >- + ../code_samples/javascript/api_v1_webauthn_credentials_{credential_id}/patch.js + - label: Python SDK + lang: python + source: + $ref: >- + ../code_samples/python/api_v1_webauthn_credentials_{credential_id}/patch.py + - label: Go SDK + lang: go + source: + $ref: >- + ../code_samples/go/api_v1_webauthn_credentials_{credential_id}/patch.go + - label: Java SDK + lang: java + source: + $ref: >- + ../code_samples/java/api_v1_webauthn_credentials_{credential_id}/patch.java + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/WebAuthnServiceUpdateCredentialBody.yaml + required: true diff --git a/openapi/saaskit.yaml b/openapi/saaskit.yaml new file mode 100644 index 000000000..ec0b33a4e --- /dev/null +++ b/openapi/saaskit.yaml @@ -0,0 +1,374 @@ +info: + description: "# Overview\n\nThe Scalekit API is a RESTful API that enables you to manage organizations, users, and authentication settings. All requests must use HTTPS.\nAll API requests use the following base URLs:\n\n```\nhttps://{your-subdomain}.scalekit.dev (Development)\nhttps://{your-subdomain}.scalekit.com (Production)\nhttps://auth.yourapp.com (Custom domain)\n```\n\nScalekit operates two separate environments: Development and Production. Resources cannot be moved between environments.\n\n## Quickstart\n\nThe Scalekit API uses OAuth 2.0 Client Credentials for authentication.\n\nCopy your API credentials from the Scalekit dashboard's API Config section and set them as environment variables.\n\n```sh\nSCALEKIT_ENVIRONMENT_URL=''\nSCALEKIT_CLIENT_ID=''\nSCALEKIT_CLIENT_SECRET=''\n```\n\nGetting an access token\n\n1. Get your credentials from the [Scalekit Dashboard](https://app.scalekit.com)\n2. Request an access token:\n\n```sh\ncurl https:///oauth/token \\\n -X POST \\\n -H 'Content-Type: application/x-www-form-urlencoded' \\\n -d 'client_id={client_id}' \\\n -d 'client_secret={client_secret}' \\\n -d 'grant_type=client_credentials'\n```\n\n3. Use the access token in API requests:\n\n```sh\ncurl https:///api/v1/organizations \\\n -H 'Content-Type: application/json' \\\n -H 'Authorization: Bearer {access_token}'\n```\n\nThe response includes an access token:\n\n```json\n{\n\t\"access_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6InNua181Ok4OTEyMjU2NiIsInR5cCI6IkpXVCJ9...\",\n\t\"token_type\": \"Bearer\",\n\t\"expires_in\": 86399,\n\t\"scope\": \"openid\"\n}\n```\n\n## SDKs\n\nScalekit provides official SDKs for multiple programming languages. Check the changelog at GitHub repositories for the latest updates.\n\n### Node.js\n\n```sh\nnpm install @scalekit-sdk/node\n```\n\nCreate a new Scalekit client instance after initializing the environment variables\n\n```js\nimport { Scalekit } from \"@scalekit-sdk/node\";\n\nexport let scalekit = new Scalekit(\n\tprocess.env.SCALEKIT_ENVIRONMENT_URL,\n\tprocess.env.SCALEKIT_CLIENT_ID,\n\tprocess.env.SCALEKIT_CLIENT_SECRET\n);\n```\n\n[See the Node SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-node/releases)\n\n### Python\n\n```sh\npip install scalekit-sdk-python\n```\n\nCreate a new Scalekit client instance after initializing the environment variables.\n\n```py\nfrom scalekit import ScalekitClient\nimport os\n\nscalekit_client = ScalekitClient(\n os.environ.get('SCALEKIT_ENVIRONMENT_URL'),\n os.environ.get('SCALEKIT_CLIENT_ID'),\n os.environ.get('SCALEKIT_CLIENT_SECRET')\n)\n```\n\n[See the Python SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-python/releases)\n\n### Go\n\n```sh\ngo get -u github.com/scalekit-inc/scalekit-sdk-go\n```\n\nCreate a new Scalekit client instance after initializing the environment variables.\n\n```go\npackage main\n\nimport (\n \"os\"\n \"github.com/scalekit-inc/scalekit-sdk-go\"\n)\n\nscalekitClient := scalekit.NewScalekitClient(\n os.Getenv(\"SCALEKIT_ENVIRONMENT_URL\"),\n os.Getenv(\"SCALEKIT_CLIENT_ID\"),\n os.Getenv(\"SCALEKIT_CLIENT_SECRET\"),\n)\n```\n\n[See the Go SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-go/releases)\n\n### Java\n\n```gradle\n/* Gradle users - add the following to your dependencies in build file */\nimplementation \"com.scalekit:scalekit-sdk-java:2.0.11\"\n```\n\n```xml\n\n\n com.scalekit\n scalekit-sdk-java\n 2.0.11\n\n```\n\n[See the Java SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-java/releases)\n\n### Error handling\n\nThe API uses standard HTTP status codes:\n\n| Code | Description |\n| ----------- | -------------------- |\n| 200/201 | Success |\n| 400 | Invalid request |\n| 401 | Authentication error |\n| 404 | Resource not found |\n| 429 | Rate limit exceeded |\n| 500/501/504 | Server error |\n\nError responses include detailed information:\n\n```json\n{\n\t\"code\": 16,\n\t\"message\": \"Token empty\",\n\t\"details\": [\n\t\t{\n\t\t\t\"@type\": \"type.googleapis.com/scalekit.v1.errdetails.ErrorInfo\",\n\t\t\t\"error_code\": \"UNAUTHENTICATED\"\n\t\t}\n\t]\n}\n```\n" + title: Scalekit APIs + contact: + name: Scalekit Inc + url: https://scalekit.com + email: support@scalekit.com + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0 + version: 1.0.0 + x-scalar-sdk-installation: + - lang: shell + description: >- + Set up OAuth 2.0 Client Credentials authentication to access Scalekit + APIs. Includes credential configuration, token exchange, and + authenticated API request examples. + source: > + + # 1. Obtain API Credentials + + # Get your credentials from the Scalekit dashboard + + export SCALEKIT_ENVIRONMENT_URL="https://your-org.scalekit.dev" # Your + Scalekit environment URL + + export SCALEKIT_CLIENT_ID="your_client_id" # Your + client ID + + export SCALEKIT_CLIENT_SECRET="your_client_secret" # Your + client secret + + + # 2. Exchange client credentials an OAuth 2.0 access token + + TOKEN_RESPONSE=$(curl -s -X POST + "${SCALEKIT_ENVIRONMENT_URL}/oauth/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "client_id=${SCALEKIT_CLIENT_ID}" \ + -d "client_secret=${SCALEKIT_CLIENT_SECRET}" \ + -d "grant_type=client_credentials") + + # 3. Make Authenticated API Requests + + curl -X GET "${SCALEKIT_ENVIRONMENT_URL}/api/v1/organizations" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${ACCESS_TOKEN}" \ + -H "Accept: application/json" +paths: + /api/v1/connections: + $ref: paths/api_v1_connections.yaml + /api/v1/invites/organizations/{organization_id}/users/{id}/resend: + $ref: >- + paths/api_v1_invites_organizations_{organization_id}_users_{id}_resend.yaml + /api/v1/memberships/organizations/{organization_id}/users/{id}: + $ref: paths/api_v1_memberships_organizations_{organization_id}_users_{id}.yaml + /api/v1/organizations: + $ref: paths/api_v1_organizations.yaml + /api/v1/organizations/{id}: + $ref: paths/api_v1_organizations_{id}.yaml + /api/v1/organizations/{id}/portal_links: + $ref: paths/api_v1_organizations_{id}_portal_links.yaml + /api/v1/organizations/{id}/settings: + $ref: paths/api_v1_organizations_{id}_settings.yaml + /api/v1/organizations/{org_id}/roles: + $ref: paths/api_v1_organizations_{org_id}_roles.yaml + /api/v1/organizations/{org_id}/roles/{role_name}: + $ref: paths/api_v1_organizations_{org_id}_roles_{role_name}.yaml + /api/v1/organizations/{org_id}/roles:set_defaults: + $ref: paths/api_v1_organizations_{org_id}_roles:set_defaults.yaml + /api/v1/organizations/{organization_id}/clients: + $ref: paths/api_v1_organizations_{organization_id}_clients.yaml + /api/v1/organizations/{organization_id}/clients/{client_id}: + $ref: paths/api_v1_organizations_{organization_id}_clients_{client_id}.yaml + /api/v1/organizations/{organization_id}/clients/{client_id}/secrets: + $ref: >- + paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets.yaml + /api/v1/organizations/{organization_id}/clients/{client_id}/secrets/{secret_id}: + $ref: >- + paths/api_v1_organizations_{organization_id}_clients_{client_id}_secrets_{secret_id}.yaml + /api/v1/organizations/{organization_id}/connections/{id}: + $ref: paths/api_v1_organizations_{organization_id}_connections_{id}.yaml + /api/v1/organizations/{organization_id}/connections/{id}:disable: + $ref: paths/api_v1_organizations_{organization_id}_connections_{id}:disable.yaml + /api/v1/organizations/{organization_id}/connections/{id}:enable: + $ref: paths/api_v1_organizations_{organization_id}_connections_{id}:enable.yaml + /api/v1/organizations/{organization_id}/directories: + $ref: paths/api_v1_organizations_{organization_id}_directories.yaml + /api/v1/organizations/{organization_id}/directories/{directory_id}/groups: + $ref: >- + paths/api_v1_organizations_{organization_id}_directories_{directory_id}_groups.yaml + /api/v1/organizations/{organization_id}/directories/{directory_id}/users: + $ref: >- + paths/api_v1_organizations_{organization_id}_directories_{directory_id}_users.yaml + /api/v1/organizations/{organization_id}/directories/{id}: + $ref: paths/api_v1_organizations_{organization_id}_directories_{id}.yaml + /api/v1/organizations/{organization_id}/directories/{id}:disable: + $ref: paths/api_v1_organizations_{organization_id}_directories_{id}:disable.yaml + /api/v1/organizations/{organization_id}/directories/{id}:enable: + $ref: paths/api_v1_organizations_{organization_id}_directories_{id}:enable.yaml + /api/v1/organizations/{organization_id}/domains: + $ref: paths/api_v1_organizations_{organization_id}_domains.yaml + /api/v1/organizations/{organization_id}/domains/{id}: + $ref: paths/api_v1_organizations_{organization_id}_domains_{id}.yaml + /api/v1/organizations/{organization_id}/session-policy: + $ref: paths/api_v1_organizations_{organization_id}_session-policy.yaml + /api/v1/organizations/{organization_id}/settings/usermanagement: + $ref: paths/api_v1_organizations_{organization_id}_settings_usermanagement.yaml + /api/v1/organizations/{organization_id}/users: + $ref: paths/api_v1_organizations_{organization_id}_users.yaml + /api/v1/organizations/{organization_id}/users/{user_id}/permissions: + $ref: >- + paths/api_v1_organizations_{organization_id}_users_{user_id}_permissions.yaml + /api/v1/organizations/{organization_id}/users/{user_id}/roles: + $ref: paths/api_v1_organizations_{organization_id}_users_{user_id}_roles.yaml + /api/v1/organizations/{organization_id}/users:search: + $ref: paths/api_v1_organizations_{organization_id}_users:search.yaml + /api/v1/organizations:external/{external_id}: + $ref: paths/api_v1_organizations:external_{external_id}.yaml + /api/v1/passwordless/email/resend: + $ref: paths/api_v1_passwordless_email_resend.yaml + /api/v1/passwordless/email/send: + $ref: paths/api_v1_passwordless_email_send.yaml + /api/v1/passwordless/email/verify: + $ref: paths/api_v1_passwordless_email_verify.yaml + /api/v1/permissions: + $ref: paths/api_v1_permissions.yaml + /api/v1/permissions/{permission_name}: + $ref: paths/api_v1_permissions_{permission_name}.yaml + /api/v1/roles: + $ref: paths/api_v1_roles.yaml + /api/v1/roles/default: + $ref: paths/api_v1_roles_default.yaml + /api/v1/roles/{role_name}: + $ref: paths/api_v1_roles_{role_name}.yaml + /api/v1/roles/{role_name}/dependents: + $ref: paths/api_v1_roles_{role_name}_dependents.yaml + /api/v1/roles/{role_name}/permissions: + $ref: paths/api_v1_roles_{role_name}_permissions.yaml + /api/v1/roles/{role_name}/permissions/{permission_name}: + $ref: paths/api_v1_roles_{role_name}_permissions_{permission_name}.yaml + /api/v1/roles/{role_name}/permissions:all: + $ref: paths/api_v1_roles_{role_name}_permissions:all.yaml + /api/v1/roles/{role_name}/users:count: + $ref: paths/api_v1_roles_{role_name}_users:count.yaml + /api/v1/roles:set_defaults: + $ref: paths/api_v1_roles:set_defaults.yaml + /api/v1/sessions/{session_id}: + $ref: paths/api_v1_sessions_{session_id}.yaml + /api/v1/sessions/{session_id}/revoke: + $ref: paths/api_v1_sessions_{session_id}_revoke.yaml + /api/v1/users: + $ref: paths/api_v1_users.yaml + /api/v1/users/{id}: + $ref: paths/api_v1_users_{id}.yaml + /api/v1/users/{user_id}/sessions: + $ref: paths/api_v1_users_{user_id}_sessions.yaml + /api/v1/users/{user_id}/sessions/revoke: + $ref: paths/api_v1_users_{user_id}_sessions_revoke.yaml + /api/v1/users:search: + $ref: paths/api_v1_users:search.yaml + /api/v1/webauthn/credentials: + $ref: paths/api_v1_webauthn_credentials.yaml + /api/v1/webauthn/credentials/{credential_id}: + $ref: paths/api_v1_webauthn_credentials_{credential_id}.yaml +tags: + - description: > + Organization represents a customer or a tenant of your product. This is + the top level entity and all resources are mapped to this Organization + object. Each organization is uniquely identified by `organization_id`. + + + + name: Organizations + - description: >- + Permission management for defining and controlling access to system + resources. Create, retrieve, update, and delete granular permissions that + represent specific actions users can perform. Permissions are the building + blocks of role-based access control (RBAC) and can be assigned to roles to + grant users the ability to perform specific operations. Use this service + to define custom permissions for your application's unique access control + requirements. + name: Permissions + - description: >- + Comprehensive user management operations including user lifecycle, + organization memberships, and invitation workflows. This service provides + endpoints for creating, retrieving, updating, and deleting user accounts + across your Scalekit environment. It supports both individual user + operations and bulk operations for user administration, including user + search, pagination, and metadata management. The service also handles user + invitations and organization membership management. + name: Users + - description: >- + Manage enterprise connections for your Scalekit environment. This service + provides endpoints for retrieving, and updating connections. + name: Connections + - description: >- + Directory management for viewing and controlling external identity + provider connections in your Scalekit environment. This service provides + endpoints for retrieving directory information, listing directories and + their contents, and enabling or disabling directory synchronization. + name: Directory + - description: >- + Role-based access control (RBAC) for defining and managing permissions in + an environment. Create and update custom roles with explicit permissions, + model role hierarchies through inheritance, view dependent roles, manage + role-permission assignments, and list roles and permissions. Also provides + a utility to count users assigned to a role. + name: Roles + - description: >- + Comprehensive session management for user authentication and + authorization. This service provides endpoints for retrieving session + details, managing user sessions across devices, revoking individual + sessions, and terminating all active sessions for a user. It supports + session auditing, device tracking, and security monitoring with detailed + session metadata including device information, IP geolocation, and + activity timestamps. + name: Sessions + - description: > + Manage organization-level domains. Scalekit supports two domain types: + + + - ORGANIZATION_DOMAIN: Used for SSO domain discovery. When a user signs in + with a matching email domain, Scalekit routes them to the organization’s + SSO provider and enforces SSO. + + - ALLOWED_EMAIL_DOMAIN: Used to mark trusted email domains for an + organization. When a user signs in or signs up with a matching domain, + Scalekit suggests the organization in the organization switcher + (authentication-method agnostic). + name: Domains + - description: >- + Endpoints for managing API client applications. API clients enable secure, + automated interactions between software systems without human + intervention. Each client is uniquely identified by a `client_id` and can + be configured with authentication settings, redirect URIs, and security + parameters. Use these endpoints to create, manage, and configure API + clients for your API clients. + name: API Auth + externalDocs: + url: https://docs.scalekit.com/m2m/overview + - description: >- + Endpoints for sending and verifying passwordless authentication emails. + These APIs allow users to authenticate without passwords by receiving a + verification code or magic link in their email. + name: Magic link & OTP + - description: Endpoints for passkey-based authentication using WebAuthn/FIDO2 standards. + name: Passkeys + +externalDocs: + description: Scalekit Docs + url: https://docs.scalekit.com/ +openapi: 3.1.1 +servers: + - url: https://$SCALEKIT_ENVIRONMENT_URL +components: + securitySchemes: + oauth2: + type: oauth2 + flows: + clientCredentials: + tokenUrl: https://$SCALEKIT_ENVIRONMENT_URL/oauth/token + scopes: + '': No scope required for client credentials flow +x-scalar-environments: + production: + variables: + SCALEKIT_ENVIRONMENT_URL: + default: https://$SCALEKIT_ENVIRONMENT_URL + description: yourapp.scalekit.com + staging: + variables: + SCALEKIT_ENVIRONMENT_URL: + default: https://$SCALEKIT_ENVIRONMENT_URL + description: yourapp.scalekit.dev +x-scalar-active-environment: staging +security: + - oauth2: [] +webhooks: + organization.created: + $ref: webhooks/organization.created.yaml + organization.updated: + $ref: webhooks/organization.updated.yaml + organization.deleted: + $ref: webhooks/organization.deleted.yaml + user.signup: + $ref: webhooks/user.signup.yaml + user.login: + $ref: webhooks/user.login.yaml + user.logout: + $ref: webhooks/user.logout.yaml + user.organization_invitation: + $ref: webhooks/user.organization_invitation.yaml + user.organization_membership_created: + $ref: webhooks/user.organization_membership_created.yaml + user.organization_membership_deleted: + $ref: webhooks/user.organization_membership_deleted.yaml + user.organization_membership_updated: + $ref: webhooks/user.organization_membership_updated.yaml + organization.directory_enabled: + $ref: webhooks/organization.directory_enabled.yaml + organization.directory_disabled: + $ref: webhooks/organization.directory_disabled.yaml + organization.directory.user_created: + $ref: webhooks/organization.directory.user_created.yaml + organization.directory.user_updated: + $ref: webhooks/organization.directory.user_updated.yaml + organization.directory.user_deleted: + $ref: webhooks/organization.directory.user_deleted.yaml + organization.directory.group_created: + $ref: webhooks/organization.directory.group_created.yaml + organization.directory.group_updated: + $ref: webhooks/organization.directory.group_updated.yaml + organization.directory.group_deleted: + $ref: webhooks/organization.directory.group_deleted.yaml + organization.sso_created: + $ref: webhooks/organization.sso_created.yaml + organization.sso_enabled: + $ref: webhooks/organization.sso_enabled.yaml + organization.sso_disabled: + $ref: webhooks/organization.sso_disabled.yaml + organization.sso_deleted: + $ref: webhooks/organization.sso_deleted.yaml + role.created: + $ref: webhooks/role.created.yaml + role.updated: + $ref: webhooks/role.updated.yaml + role.deleted: + $ref: webhooks/role.deleted.yaml + permission.created: + $ref: webhooks/permission.created.yaml + permission.updated: + $ref: webhooks/permission.updated.yaml + permission.deleted: + $ref: webhooks/permission.deleted.yaml + diff --git a/openapi/webhooks/connected_account.created.yaml b/openapi/webhooks/connected_account.created.yaml new file mode 100644 index 000000000..4225a519e --- /dev/null +++ b/openapi/webhooks/connected_account.created.yaml @@ -0,0 +1,25 @@ +post: + summary: Connected Account Created + description: Triggered when a new connected account is created + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_101531404017336586 + type: connected_account.created + object: ConnectedAccount + occurred_at: '2025-12-01T10:23:52.702980847Z' + environment_id: env_88640229614813449 + data: + authorization_type: OAUTH + connection_id: conn_100668583155073286 + id: ca_101531404000559370 + identifier: Bruce + provider: CANVA + status: PENDING_AUTH + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/connected_account.deleted.yaml b/openapi/webhooks/connected_account.deleted.yaml new file mode 100644 index 000000000..2ae5f5856 --- /dev/null +++ b/openapi/webhooks/connected_account.deleted.yaml @@ -0,0 +1,28 @@ +post: + summary: Connected Account Deleted + description: Triggered when a connected account is deleted + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_101653010731500290 + type: connected_account.deleted + object: ConnectedAccount + occurred_at: '2025-12-02T06:31:55.954027187Z' + environment_id: env_88640229614813449 + display_name: connected account deleted + data: + authorization_type: OAUTH + connection_id: conn_101644109747323155 + id: ca_101649788113519113 + identifier: Clark + last_used_at: '2025-12-02T06:00:01.374253Z' + provider: GOOGLE_ADS + status: ACTIVE + token_expires_at: '2025-12-02T06:59:57.237447Z' + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/connected_account.magic_link_generated.yaml b/openapi/webhooks/connected_account.magic_link_generated.yaml new file mode 100644 index 000000000..6b54bbc45 --- /dev/null +++ b/openapi/webhooks/connected_account.magic_link_generated.yaml @@ -0,0 +1,25 @@ +post: + summary: Connected Account Magic Link Generated + description: Triggered when a magic link is generated for OAuth flow + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_101652975398683158 + type: connected_account.magic_link_generated + object: ConnectedAccount + occurred_at: '2025-12-02T06:31:34.895815554Z' + environment_id: env_88640229614813448 + data: + authorization_type: OAUTH + connection_id: conn_100510054016352776 + id: ca_100510623602835982 + identifier: Pranesh + provider: SUPABASE + status: PENDING_AUTH + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/connected_account.oauth_succeeded.yaml b/openapi/webhooks/connected_account.oauth_succeeded.yaml new file mode 100644 index 000000000..2796bb029 --- /dev/null +++ b/openapi/webhooks/connected_account.oauth_succeeded.yaml @@ -0,0 +1,26 @@ +post: + summary: Connected Account OAuth Succeeded + description: Triggered when OAuth authentication succeeds + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_101649484227871236 + type: connected_account.oauth_succeeded + object: ConnectedAccount + occurred_at: '2025-12-02T05:56:53.994604757Z' + environment_id: env_88640229614813449 + data: + authorization_type: OAUTH + connection_id: conn_101644109747323155 + id: ca_101649474950005257 + identifier: Bruce + provider: GOOGLE_ADS + status: ACTIVE + token_expires_at: '2025-12-02T06:56:52.976081699Z' + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/connected_account.oauth_tokens_fetched.yaml b/openapi/webhooks/connected_account.oauth_tokens_fetched.yaml new file mode 100644 index 000000000..92b293ac0 --- /dev/null +++ b/openapi/webhooks/connected_account.oauth_tokens_fetched.yaml @@ -0,0 +1,26 @@ +post: + summary: Connected Account OAuth Tokens Fetched + description: Triggered when OAuth tokens are successfully fetched + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_101649795042509316 + type: connected_account.oauth_tokens_fetched + object: ConnectedAccount + occurred_at: '2025-12-02T05:59:59.250126407Z' + environment_id: env_88640229614813449 + data: + authorization_type: OAUTH + connection_id: conn_101644109747323155 + id: ca_101649788113519113 + identifier: Clark + provider: GOOGLE_ADS + status: ACTIVE + token_expires_at: '2025-12-02T06:59:57.237447778Z' + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/connected_account.token_refresh_failed.yaml b/openapi/webhooks/connected_account.token_refresh_failed.yaml new file mode 100644 index 000000000..c23b49918 --- /dev/null +++ b/openapi/webhooks/connected_account.token_refresh_failed.yaml @@ -0,0 +1,26 @@ +post: + summary: Connected Account Token Refresh Failed + description: Triggered when token refresh fails + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_101649795042509316 + type: connected_account.token_refresh_failed + object: ConnectedAccount + occurred_at: '2025-12-02T05:59:59.250126407Z' + environment_id: env_88640229614813445 + data: + authorization_type: OAUTH + connection_id: conn_101644109747323155 + id: ca_101649788113519113 + identifier: Clark + provider: GOOGLE_ADS + status: ACTIVE + token_expires_at: '2025-12-02T06:59:57.237447778Z' + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/connected_account.token_refresh_succeeded.yaml b/openapi/webhooks/connected_account.token_refresh_succeeded.yaml new file mode 100644 index 000000000..c151ad99b --- /dev/null +++ b/openapi/webhooks/connected_account.token_refresh_succeeded.yaml @@ -0,0 +1,27 @@ +post: + summary: Connected Account Token Refresh Succeeded + description: Triggered when token refresh succeeds + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_101651946317808143 + type: connected_account.token_refresh_succeeded + object: ConnectedAccount + occurred_at: '2025-12-02T06:21:21.517480021Z' + environment_id: env_88640229614813449 + data: + authorization_type: OAUTH + connection_id: conn_101644109747323155 + id: ca_101644170698948883 + identifier: Pranesh + last_used_at: '2025-12-02T06:21:21.393723232Z' + provider: GOOGLE_ADS + status: ACTIVE + token_expires_at: '2025-12-02T07:21:20.508197312Z' + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/connected_account.updated.yaml b/openapi/webhooks/connected_account.updated.yaml new file mode 100644 index 000000000..40fa95787 --- /dev/null +++ b/openapi/webhooks/connected_account.updated.yaml @@ -0,0 +1,26 @@ +post: + summary: Connected Account Updated + description: Triggered when a connected account is updated + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_101652975398683158 + type: connected_account.updated + object: ConnectedAccount + occurred_at: '2025-12-02T06:31:34.895815554Z' + environment_id: env_88640229614813449 + display_name: Connected account updated + data: + authorization_type: OAUTH + connection_id: conn_100510054016352776 + id: ca_100510623602835982 + identifier: Pranesh + provider: SUPABASE + status: PENDING_AUTH + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.created.yaml b/openapi/webhooks/organization.created.yaml new file mode 100644 index 000000000..92ae035d1 --- /dev/null +++ b/openapi/webhooks/organization.created.yaml @@ -0,0 +1,34 @@ +post: + summary: Organization Created + description: Triggered when a new organization is created in Scalekit + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_1234567890 + type: organization.created + object: Organization + occurred_at: '2024-01-15T10:30:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_1234567890 + data: + create_time: '2025-12-09T09:25:02.02Z' + display_name: AcmeCorp + external_id: org_external_123 + id: org_1234567890 + metadata: null + region_code: US + update_time: '2025-12-09T09:25:02.025330364Z' + settings: + features: + - enabled: true + name: sso + - enabled: false + name: dir_sync + display_name: Organization Created + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.deleted.yaml b/openapi/webhooks/organization.deleted.yaml new file mode 100644 index 000000000..d5790626b --- /dev/null +++ b/openapi/webhooks/organization.deleted.yaml @@ -0,0 +1,35 @@ +post: + summary: Organization Deleted + description: Triggered when an organization is deleted + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_3456789012 + type: organization.deleted + object: Organization + occurred_at: '2024-01-15T10:40:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_1234567890 + data: + create_time: '2025-12-09T09:25:02.02Z' + deleted_at: '2025-12-09T10:25:45.337417Z' + display_name: AcmeCorp + external_id: org_external_123 + id: org_1234567890 + metadata: null + region_code: US + update_time: '2025-12-09T09:25:02.025330364Z' + settings: + features: + - enabled: true + name: sso + - enabled: false + name: dir_sync + display_name: Organization Deleted + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.directory.group_created.yaml b/openapi/webhooks/organization.directory.group_created.yaml new file mode 100644 index 000000000..3fd5ec356 --- /dev/null +++ b/openapi/webhooks/organization.directory.group_created.yaml @@ -0,0 +1,27 @@ +post: + summary: Directory Group Created + description: Triggered when a new directory group is created + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_38862741515010639 + type: organization.directory.group_created + object: DirectoryGroup + occurred_at: '2024-09-25T02:26:39.036398577Z' + environment_id: env_32080745237316098 + organization_id: org_38609339635728478 + data: + directory_id: dir_38610496391217780 + display_name: Avengers + external_id: null + id: dirgroup_38862741498233423 + organization_id: org_38609339635728478 + raw_attributes: {} + display_name: Directory Group Created + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.directory.group_deleted.yaml b/openapi/webhooks/organization.directory.group_deleted.yaml new file mode 100644 index 000000000..0583516de --- /dev/null +++ b/openapi/webhooks/organization.directory.group_deleted.yaml @@ -0,0 +1,27 @@ +post: + summary: Directory Group Deleted + description: Triggered when a directory group is deleted + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_40650399597723966 + type: organization.directory.group_deleted + object: DirectoryGroup + occurred_at: '2024-10-07T10:25:26.289331747Z' + environment_id: env_12205603854221623 + organization_id: org_39802449573184223 + data: + directory_id: dir_39802485862301855 + display_name: Admins + dp_id: 7c66a173-79c6-4270-ac78-8f35a8121e0a + id: dirgroup_40072007005503806 + organization_id: org_39802449573184223 + raw_attributes: {} + display_name: Directory Group Deleted + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.directory.group_updated.yaml b/openapi/webhooks/organization.directory.group_updated.yaml new file mode 100644 index 000000000..99c312940 --- /dev/null +++ b/openapi/webhooks/organization.directory.group_updated.yaml @@ -0,0 +1,27 @@ +post: + summary: Directory Group Updated + description: Triggered when a directory group is updated + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_38864948910162368 + type: organization.directory.group_updated + object: DirectoryGroup + occurred_at: '2024-09-25T02:48:34.745030921Z' + environment_id: env_32080745237316098 + organization_id: org_38609339635728478 + data: + directory_id: dir_38610496391217780 + display_name: Avengers + external_id: + id: dirgroup_38862741498233423 + organization_id: org_38609339635728478 + raw_attributes: {} + display_name: Directory Group Updated + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.directory.user_created.yaml b/openapi/webhooks/organization.directory.user_created.yaml new file mode 100644 index 000000000..9ccbbf44f --- /dev/null +++ b/openapi/webhooks/organization.directory.user_created.yaml @@ -0,0 +1,51 @@ +post: + summary: Directory User Created + description: Triggered when a new directory user is created + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_53891546994442316 + type: organization.directory.user_created + object: DirectoryUser + occurred_at: '2025-01-06T18:44:25.153954Z' + environment_id: env_53814739859406915 + organization_id: org_53879494091473415 + data: + active: true + cost_center: QAUZJUHSTYCN + custom_attributes: + mobile_phone_number: 1-579-4072 + department: HNXJPGISMIFN + division: MJFUEYJOKICN + dp_id: + email: flavio@runolfsdottir.co.duk + employee_id: AWNEDTILGaIZN + family_name: Jaquelin + given_name: Dayton + groups: + - id: dirgroup_12312312312312 + name: Group Name + id: diruser_53891546960887884 + language: se + locale: LLWLEWESPLDC + name: QDRGUZZDYMFU + nickname: DTUODYKGFPPC + organization: AUIITQVUQGVH + organization_id: org_53879494091473415 + phone_number: 1-579-4072 + preferred_username: kuntala1233a + profile: YMIUQUHKGVAX + raw_attributes: {} + title: FKQBHCWJXZSC + user_type: RBQFJSQEFAEH + zoneinfo: America/Araguaina + roles: + - role_name: billing_admin + display_name: Directory User Created + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.directory.user_deleted.yaml b/openapi/webhooks/organization.directory.user_deleted.yaml new file mode 100644 index 000000000..cc00555eb --- /dev/null +++ b/openapi/webhooks/organization.directory.user_deleted.yaml @@ -0,0 +1,25 @@ +post: + summary: Directory User Deleted + description: Triggered when a directory user is deleted + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_53891546994442318 + type: organization.directory.user_deleted + object: DirectoryUser + occurred_at: '2025-01-06T18:44:25.153954Z' + environment_id: env_53814739859406915 + organization_id: org_53879494091473415 + data: + id: diruser_12312312312312 + organization_id: org_12312312312312 + dp_id: + email: john.doe@example.com + display_name: Directory User Deleted + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.directory.user_updated.yaml b/openapi/webhooks/organization.directory.user_updated.yaml new file mode 100644 index 000000000..b6fb34ce8 --- /dev/null +++ b/openapi/webhooks/organization.directory.user_updated.yaml @@ -0,0 +1,46 @@ +post: + summary: Directory User Updated + description: Triggered when a directory user is updated + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_53891546994442317 + type: organization.directory.user_updated + object: DirectoryUser + occurred_at: '2025-01-06T18:44:25.153954Z' + environment_id: env_53814739859406915 + organization_id: org_53879494091473415 + data: + id: diruser_12312312312312 + organization_id: org_53879494091473415 + dp_id: + preferred_username: + email: john.doe@example.com + active: true + name: John Doe + roles: + - role_name: billing_admin + groups: + - id: dirgroup_12312312312312 + name: Group Name + given_name: John + family_name: Doe + nickname: Jhonny boy + picture: https://image.com/profile.jpg + phone_number: '1234567892' + address: + postal_code: '64112' + state: Missouri + formatted: 123, Oxford Lane, Kansas City, Missouri, 64112 + custom_attributes: + attribute1: value1 + attribute2: value2 + raw_attributes: {} + display_name: Directory User Updated + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.directory_disabled.yaml b/openapi/webhooks/organization.directory_disabled.yaml new file mode 100644 index 000000000..f3f61d2e2 --- /dev/null +++ b/openapi/webhooks/organization.directory_disabled.yaml @@ -0,0 +1,27 @@ +post: + summary: Directory Disabled + description: Triggered when a directory sync is disabled + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_53891640779079756 + type: organization.directory_disabled + object: Directory + occurred_at: '2025-01-06T18:45:21.057814Z' + environment_id: env_53814739859406915 + organization_id: org_53879494091473415 + data: + directory_type: SCIM + enabled: false + id: dir_53879621145330183 + organization_id: org_53879494091473415 + provider: OKTA + updated_at: '2025-01-06T18:45:21.04978184Z' + display_name: Directory Disabled + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.directory_enabled.yaml b/openapi/webhooks/organization.directory_enabled.yaml new file mode 100644 index 000000000..ce766f2db --- /dev/null +++ b/openapi/webhooks/organization.directory_enabled.yaml @@ -0,0 +1,27 @@ +post: + summary: Directory Enabled + description: Triggered when a directory sync is enabled + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_55136848686613000 + type: organization.directory_enabled + object: Directory + occurred_at: '2025-01-15T08:55:22.802860294Z' + environment_id: env_27758032200925221 + organization_id: org_55135410258444802 + data: + directory_type: SCIM + enabled: true + id: dir_55135622825771522 + organization_id: org_55135410258444802 + provider: OKTA + updated_at: '2025-01-15T08:55:22.792993454Z' + display_name: Directory Enabled + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.sso_created.yaml b/openapi/webhooks/organization.sso_created.yaml new file mode 100644 index 000000000..2439ab3b9 --- /dev/null +++ b/openapi/webhooks/organization.sso_created.yaml @@ -0,0 +1,25 @@ +post: + summary: SSO Connection Created + description: Triggered when a new SSO connection is created for an organization + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_94567862441607493 + type: organization.sso_created + object: Connection + environment_id: env_74418471961625391 + occurred_at: '2025-10-14T09:27:18.488720586Z' + organization_id: org_83544995172188677 + data: + id: conn_94567862424830277 + organization_id: org_83544995172188677 + connection_type: OIDC + provider: OKTA + display_name: SSO Connection Created + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.sso_deleted.yaml b/openapi/webhooks/organization.sso_deleted.yaml new file mode 100644 index 000000000..5dd9aaa3b --- /dev/null +++ b/openapi/webhooks/organization.sso_deleted.yaml @@ -0,0 +1,25 @@ +post: + summary: SSO Connection Deleted + description: Triggered when an SSO connection is deleted for an organization + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_94557997639926040 + type: organization.sso_deleted + object: Connection + environment_id: env_74418471961625391 + occurred_at: '2025-10-14T07:49:18.604546332Z' + organization_id: org_83544995172188677 + data: + id: conn_83545002856153607 + organization_id: org_83544995172188677 + connection_type: OIDC + provider: OKTA + display_name: SSO Connection Deleted + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.sso_disabled.yaml b/openapi/webhooks/organization.sso_disabled.yaml new file mode 100644 index 000000000..414df02f0 --- /dev/null +++ b/openapi/webhooks/organization.sso_disabled.yaml @@ -0,0 +1,27 @@ +post: + summary: SSO Connection Disabled + description: Triggered when an SSO connection is disabled for an organization + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_94557976165089560 + type: organization.sso_disabled + object: Connection + environment_id: env_74418471961625391 + occurred_at: '2025-10-14T07:49:05.809554456Z' + organization_id: org_83544995172188677 + data: + id: conn_83545002856153607 + organization_id: org_83544995172188677 + connection_type: OIDC + provider: OKTA + enabled: false + status: COMPLETED + display_name: SSO Connection Disabled + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.sso_enabled.yaml b/openapi/webhooks/organization.sso_enabled.yaml new file mode 100644 index 000000000..bdeec8119 --- /dev/null +++ b/openapi/webhooks/organization.sso_enabled.yaml @@ -0,0 +1,27 @@ +post: + summary: SSO Connection Enabled + description: Triggered when an SSO connection is enabled for an organization + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_94568078213382471 + type: organization.sso_enabled + object: Connection + environment_id: env_74418471961625391 + occurred_at: '2025-10-14T09:29:27.098914861Z' + organization_id: org_83544995172188677 + data: + id: conn_94567862424830277 + organization_id: org_83544995172188677 + connection_type: OIDC + provider: OKTA + enabled: true + status: COMPLETED + display_name: SSO Connection Enabled + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/organization.updated.yaml b/openapi/webhooks/organization.updated.yaml new file mode 100644 index 000000000..fcce44391 --- /dev/null +++ b/openapi/webhooks/organization.updated.yaml @@ -0,0 +1,34 @@ +post: + summary: Organization Updated + description: Triggered when an organization is updated + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_2345678901 + type: organization.updated + object: Organization + occurred_at: '2024-01-15T10:35:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_1234567890 + data: + create_time: '2025-12-09T09:25:02.02Z' + display_name: AcmeCorp + external_id: org_external_123 + id: org_1234567890 + metadata: null + region_code: US + update_time: '2025-12-09T09:25:02.025330364Z' + settings: + features: + - enabled: true + name: sso + - enabled: false + name: dir_sync + display_name: Organization Updated + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/permission.created.yaml b/openapi/webhooks/permission.created.yaml new file mode 100644 index 000000000..ad0fdbb62 --- /dev/null +++ b/openapi/webhooks/permission.created.yaml @@ -0,0 +1,23 @@ +post: + summary: Permission Created + description: Triggered when a new permission is created + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_1234567890 + type: permission.created + object: Permission + occurred_at: '2024-01-15T10:30:00.123456789Z' + environment_id: env_1234567890 + data: + description: Permission to manage data + id: perm_1234567890 + name: data:manage + display_name: Permission Created + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/permission.deleted.yaml b/openapi/webhooks/permission.deleted.yaml new file mode 100644 index 000000000..fed7ca704 --- /dev/null +++ b/openapi/webhooks/permission.deleted.yaml @@ -0,0 +1,23 @@ +post: + summary: Permission Deleted + description: Triggered when a permission is deleted + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_3456789012 + type: permission.deleted + object: Permission + occurred_at: '2024-01-15T10:40:00.123456789Z' + environment_id: env_1234567890 + data: + description: Updated permission to manage all data + id: perm_1234567890 + name: data:manage + display_name: Permission Deleted + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/permission.updated.yaml b/openapi/webhooks/permission.updated.yaml new file mode 100644 index 000000000..5c67972b0 --- /dev/null +++ b/openapi/webhooks/permission.updated.yaml @@ -0,0 +1,23 @@ +post: + summary: Permission Updated + description: Triggered when a permission is updated + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_2345678901 + type: permission.updated + object: Permission + occurred_at: '2024-01-15T10:35:00.123456789Z' + environment_id: env_1234567890 + data: + description: Updated permission to manage all data + id: perm_1234567890 + name: data:manage + display_name: Permission Updated + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/role.created.yaml b/openapi/webhooks/role.created.yaml new file mode 100644 index 000000000..e84dac0d0 --- /dev/null +++ b/openapi/webhooks/role.created.yaml @@ -0,0 +1,25 @@ +post: + summary: Role Created + description: Triggered when a new role is created + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_1234567890 + type: role.created + object: Role + occurred_at: '2024-01-15T10:30:00.123456789Z' + environment_id: env_1234567890 + data: + description: Viewer role with read-only access + display_name: Viewer + extends: member + id: role_1234567890 + name: viewer + display_name: Role Created + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/role.deleted.yaml b/openapi/webhooks/role.deleted.yaml new file mode 100644 index 000000000..cfd4e324a --- /dev/null +++ b/openapi/webhooks/role.deleted.yaml @@ -0,0 +1,25 @@ +post: + summary: Role Deleted + description: Triggered when a role is deleted + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_3456789012 + type: role.deleted + object: Role + occurred_at: '2024-01-15T10:40:00.123456789Z' + environment_id: env_1234567890 + data: + description: Updated viewer role with limited permissions + display_name: Viewer + extends: member + id: role_1234567890 + name: viewer + display_name: Role Deleted + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/role.updated.yaml b/openapi/webhooks/role.updated.yaml new file mode 100644 index 000000000..0baead23f --- /dev/null +++ b/openapi/webhooks/role.updated.yaml @@ -0,0 +1,25 @@ +post: + summary: Role Updated + description: Triggered when a role is updated + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_2345678901 + type: role.updated + object: Role + occurred_at: '2024-01-15T10:35:00.123456789Z' + environment_id: env_1234567890 + data: + description: Updated viewer role with limited permissions + display_name: Viewer + extends: member + id: role_1234567890 + name: viewer + display_name: Role Updated + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/user.login.yaml b/openapi/webhooks/user.login.yaml new file mode 100644 index 000000000..91ae8344b --- /dev/null +++ b/openapi/webhooks/user.login.yaml @@ -0,0 +1,84 @@ +post: + summary: User Login + description: Triggered when a user logs in and a session is created + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_102701193859432713 + type: user.login + object: User + occurred_at: '2025-12-09T12:04:41.781873312Z' + environment_id: env_96736846679245078 + organization_id: org_102701193188409609 + data: + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + last_login_time: '2025-12-09T12:04:41.48Z' + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + family_name: Doe + gender: '' + given_name: John + groups: null + id: usp_102701193205186825 + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + user_session: + absolute_expires_at: '2026-01-08T12:04:41.737394Z' + authenticated_organizations: + - org_102701193188409609 + created_at: '2025-12-09T12:04:41.48Z' + expired_at: null + idle_expires_at: '2025-12-16T12:04:41.737395Z' + last_active_at: '2025-12-09T12:04:41.747206Z' + logout_at: null + organization_id: org_102701193188409609 + session_id: ses_102701193356116233 + status: ACTIVE + updated_at: '2025-12-09T12:04:41.748512Z' + user_id: usr_102701193205121289 + device: + browser: Chrome + browser_version: 142.0.0.0 + device_type: Desktop + ip: 152.59.144.211 + location: + city: Patna + latitude: '25.594095' + longitude: '85.137564' + region: IN + region_subdivision: INBR + os: macOS + os_version: 10.15.7 + user_agent: >- + Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) + AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 + Safari/537.36 + display_name: User Login + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/user.logout.yaml b/openapi/webhooks/user.logout.yaml new file mode 100644 index 000000000..bf3d7178a --- /dev/null +++ b/openapi/webhooks/user.logout.yaml @@ -0,0 +1,84 @@ +post: + summary: User Logout + description: Triggered when a user's session is terminated + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_102708230123160586 + type: user.logout + object: User + occurred_at: '2025-12-09T13:14:35.722070822Z' + environment_id: env_96736846679245078 + organization_id: org_102701193188409609 + data: + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + last_login_time: '2025-12-09T12:04:41.48Z' + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + family_name: Doe + gender: '' + given_name: John + groups: null + id: usp_102701193205186825 + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + user_session: + absolute_expires_at: '2026-01-08T12:04:41.737394Z' + authenticated_organizations: + - org_102701193188409609 + created_at: '2025-12-09T12:04:41.48Z' + expired_at: null + idle_expires_at: '2025-12-16T12:04:41.737395Z' + last_active_at: '2025-12-09T12:04:41.747206Z' + logout_at: null + organization_id: org_102701193188409609 + session_id: ses_102701193356116233 + status: ACTIVE + updated_at: '2025-12-09T12:04:41.748512Z' + user_id: usr_102701193205121289 + device: + browser: Chrome + browser_version: 142.0.0.0 + device_type: Desktop + ip: 152.59.144.211 + location: + city: Patna + latitude: '25.594095' + longitude: '85.137564' + region: IN + region_subdivision: INBR + os: macOS + os_version: 10.15.7 + user_agent: >- + Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) + AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 + Safari/537.36 + display_name: User Logout + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/user.organization_invitation.yaml b/openapi/webhooks/user.organization_invitation.yaml new file mode 100644 index 000000000..acb879d6d --- /dev/null +++ b/openapi/webhooks/user.organization_invitation.yaml @@ -0,0 +1,66 @@ +post: + summary: User Organization Invitation + description: Triggered when a user is invited to join an organization + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_4567890123 + type: user.organization_invitation + object: OrgMembership + occurred_at: '2024-01-15T11:00:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_102690563312124938 + data: + organization: + id: org_102690563312124938 + create_time: '2025-12-09T10:19:05.48Z' + display_name: Acme Corp + external_id: org_external_123 + metadata: null + region_code: US + update_time: '2025-12-09T12:04:41.386974738Z' + settings: + features: + - enabled: true + name: sso + - enabled: true + name: dir_sync + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + family_name: Doe + gender: '' + given_name: John + groups: null + id: usp_102701193205186825 + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + display_name: User Organization Invitation + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/user.organization_membership_created.yaml b/openapi/webhooks/user.organization_membership_created.yaml new file mode 100644 index 000000000..26713801a --- /dev/null +++ b/openapi/webhooks/user.organization_membership_created.yaml @@ -0,0 +1,66 @@ +post: + summary: User Organization Membership Created + description: Triggered when a user joins an organization + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_5678901234 + type: user.organization_membership_created + object: OrgMembership + occurred_at: '2024-01-15T11:05:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_102690563312124938 + data: + organization: + id: org_102690563312124938 + create_time: '2025-12-09T10:19:05.48Z' + display_name: Acme Corp + external_id: org_external_123 + metadata: null + region_code: US + update_time: '2025-12-09T12:04:41.386974738Z' + settings: + features: + - enabled: true + name: sso + - enabled: true + name: dir_sync + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + family_name: Doe + gender: '' + given_name: John + groups: null + id: usp_102701193205186825 + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + display_name: User Organization Membership Created + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/user.organization_membership_deleted.yaml b/openapi/webhooks/user.organization_membership_deleted.yaml new file mode 100644 index 000000000..2bbce2ff1 --- /dev/null +++ b/openapi/webhooks/user.organization_membership_deleted.yaml @@ -0,0 +1,66 @@ +post: + summary: User Organization Membership Deleted + description: Triggered when a user's membership in an organization is removed or deleted + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_9012345678 + type: user.organization_membership_deleted + object: OrgMembership + occurred_at: '2024-01-15T11:10:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_102690563312124938 + data: + organization: + id: org_102690563312124938 + create_time: '2025-12-09T10:19:05.48Z' + display_name: Acme Corp + external_id: org_external_123 + metadata: null + region_code: US + update_time: '2025-12-09T12:04:41.386974738Z' + settings: + features: + - enabled: true + name: sso + - enabled: true + name: dir_sync + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + raw_attributes: '{}' + updated_time: '2025-12-09T12:04:41.473087Z' + family_name: Doe + gender: '' + given_name: John + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + display_name: User Organization Membership Deleted + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/user.organization_membership_updated.yaml b/openapi/webhooks/user.organization_membership_updated.yaml new file mode 100644 index 000000000..a67f23100 --- /dev/null +++ b/openapi/webhooks/user.organization_membership_updated.yaml @@ -0,0 +1,68 @@ +post: + summary: User Organization Membership Updated + description: >- + Triggered when a user's organization membership is updated, e.g., change of + user's role in an organization + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_6789012345 + type: user.organization_membership_updated + object: OrgMembership + occurred_at: '2024-01-15T11:10:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_102690563312124938 + data: + organization: + id: org_102690563312124938 + create_time: '2025-12-09T10:19:05.48Z' + display_name: Acme Corp + external_id: org_external_123 + metadata: null + region_code: US + update_time: '2025-12-09T12:04:41.386974738Z' + settings: + features: + - enabled: true + name: sso + - enabled: true + name: dir_sync + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + raw_attributes: '{}' + updated_time: '2025-12-09T12:04:41.473087Z' + family_name: Doe + gender: '' + given_name: John + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + display_name: User Organization Membership Updated + responses: + '200': + description: Webhook received successfully diff --git a/openapi/webhooks/user.signup.yaml b/openapi/webhooks/user.signup.yaml new file mode 100644 index 000000000..373b7ba96 --- /dev/null +++ b/openapi/webhooks/user.signup.yaml @@ -0,0 +1,58 @@ +post: + summary: User Signup + description: Triggered when a user signs up to create a new organization + requestBody: + content: + application/json: + schema: + $ref: ../components/schemas/ScalekitEvent.yaml + example: + spec_version: '1' + id: evt_1234567890 + type: user.signup + object: OrgMembership + occurred_at: '2024-01-15T10:30:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_102690563312124938 + data: + organization: + id: org_102690563312124938 + create_time: '2025-12-09T10:19:05.48Z' + display_name: '' + external_id: null + metadata: null + region_code: US + update_time: '2025-12-09T12:04:41.386974738Z' + settings: + features: + - enabled: true + name: sso + - enabled: true + name: dir_sync + user: + create_time: '2025-12-09T12:04:41.39Z' + email: amit.ash1996@gmail.com + external_id: '' + id: usr_102701193205121289 + metadata: {} + update_time: '2025-12-09T12:04:41.391988278Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: null + family_name: doe + gender: '' + given_name: John + groups: null + id: usp_102701193205186825 + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + display_name: User Signup + responses: + '200': + description: Webhook received successfully diff --git a/package.json b/package.json index b6540c2b1..cf274d005 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "format:check": "prettier --check '**/*.{md,mdx,js,ts,astro,css,vue}'", "format": "prettier --write '**/*.{md,mdx,js,ts,astro,css,vue}'", "reorder-swagger": "node scripts/reorder-swagger.js public/api/scalekit.scalar.json", + "split-api": "redocly split public/api/scalekit.scalar.yaml --outDir=openapi && redocly bundle agentkit --remove-unused-components && redocly bundle saaskit --remove-unused-components", + "split-api:lint": "redocly lint openapi/agentkit.yaml && redocly lint openapi/saaskit.yaml", "sync-agent-connectors": "node scripts/sync-agent-connectors.js" }, "dependencies": { @@ -67,6 +69,7 @@ }, "devDependencies": { "@astrojs/check": "^0.9.8", + "@redocly/cli": "^2.31.2", "@scalar/openapi-to-markdown": "^0.5.6", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa87097b5..589dad181 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -154,6 +154,9 @@ importers: '@astrojs/check': specifier: ^0.9.8 version: 0.9.8(prettier-plugin-astro@0.14.1)(prettier@3.8.3)(typescript@6.0.3) + '@redocly/cli': + specifier: ^2.31.2 + version: 2.31.2(@opentelemetry/api@1.9.1)(core-js@3.49.0) '@scalar/openapi-to-markdown': specifier: ^0.5.6 version: 0.5.6(typescript@6.0.3) @@ -617,6 +620,12 @@ packages: '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + '@emotion/is-prop-valid@1.4.0': + resolution: {integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==} + + '@emotion/memoize@0.9.0': + resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} + '@envelop/instrumentation@1.0.0': resolution: {integrity: sha512-cxgkB66RQB95H3X27jlnxCRNTmPuSTgmBAq6/4n2Dtv4hsk4yz8FadA1ggmd0uZzvKqWD6CR+WFgTjhDqg7eyw==} engines: {node: '>=18.0.0'} @@ -936,6 +945,9 @@ packages: cpu: [x64] os: [win32] + '@exodus/schemasafe@1.3.0': + resolution: {integrity: sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==} + '@expressive-code/core@0.41.7': resolution: {integrity: sha512-ck92uZYZ9Wba2zxkiZLsZGi9N54pMSAVdrI9uW3Oo9AtLglD5RmrdTwbYPCT2S/jC36JGB2i+pnQtBm/Ib2+dg==} @@ -954,6 +966,10 @@ packages: '@expressive-code/plugin-text-markers@0.41.7': resolution: {integrity: sha512-Ewpwuc5t6eFdZmWlFyeuy3e1PTQC0jFvw2Q+2bpcWXbOZhPLsT7+h8lsSIJxb5mS7wZko7cKyQ2RLYDyK6Fpmw==} + '@faker-js/faker@7.6.0': + resolution: {integrity: sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==} + engines: {node: '>=14.0.0', npm: '>=6.0.0'} + '@fastify/accept-negotiator@2.0.1': resolution: {integrity: sha512-/c/TW2bO/v9JeEgoD/g1G5GxGeCF1Hafdf79WPmUlgYiBXummY0oX3VVq4yFkKKVBKDNlaDUYoab7g38RpPqCQ==} @@ -1547,6 +1563,10 @@ packages: engines: {node: '>=18.14.0'} hasBin: true + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + '@nodable/entities@1.1.0': resolution: {integrity: sha512-bidpxmTBP0pOsxULw6XlxzQpTgrAGLDHGBK/JuWhPDL6ZV0GZ/PmN9CA9do6e+A9lYI6qx6ikJUtJYRxup141g==} @@ -1704,6 +1724,10 @@ packages: resolution: {integrity: sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==} engines: {node: '>=8.0.0'} + '@opentelemetry/api-logs@0.214.0': + resolution: {integrity: sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA==} + engines: {node: '>=8.0.0'} + '@opentelemetry/api@1.8.0': resolution: {integrity: sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==} engines: {node: '>=8.0.0'} @@ -1722,18 +1746,48 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/context-async-hooks@2.6.1': + resolution: {integrity: sha512-XHzhwRNkBpeP8Fs/qjGrAf9r9PRv67wkJQ/7ZPaBQQ68DYlTBBx5MF9LvPx7mhuXcDessKK2b+DcxqwpgkcivQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/core@1.30.1': resolution: {integrity: sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/core@2.6.1': + resolution: {integrity: sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/exporter-trace-otlp-http@0.214.0': + resolution: {integrity: sha512-kIN8nTBMgV2hXzV/a20BCFilPZdAIMYYJGSgfMMRm/Xa+07y5hRDS2Vm12A/z8Cdu3Sq++ZvJfElokX2rkgGgw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation@0.203.0': resolution: {integrity: sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/otlp-exporter-base@0.214.0': + resolution: {integrity: sha512-u1Gdv0/E9wP+apqWf7Wv2npXmgJtxsW2XL0TEv9FZloTZRuMBKmu8cYVXwS4Hm3q/f/3FuCnPTgiwYvIqRSpRg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-transformer@0.214.0': + resolution: {integrity: sha512-DSaYcuBRh6uozfsWN3R8HsN0yDhCuWP7tOFdkUOVaWD1KVJg8m4qiLUsg/tNhTLS9HUYUcwNpwL2eroLtsZZ/w==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/propagator-b3@1.30.1': resolution: {integrity: sha512-oATwWWDIJzybAZ4pO76ATN5N6FFbOA1otibAVlS8v90B4S1wClnhRUk7K+2CHAwN1JKYuj4jh/lpCEG5BAqFuQ==} engines: {node: '>=14'} @@ -1752,22 +1806,56 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/resources@2.6.1': + resolution: {integrity: sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-logs@0.214.0': + resolution: {integrity: sha512-zf6acnScjhsaBUU22zXZ/sLWim1dfhUAbGXdMmHmNG3LfBnQ3DKsOCITb2IZwoUsNNMTogqFKBnlIPPftUgGwA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.4.0 <1.10.0' + + '@opentelemetry/sdk-metrics@2.6.1': + resolution: {integrity: sha512-9t9hJHX15meBy2NmTJxL+NJfXmnausR2xUDvE19XQce0Qi/GBtDGamU8nS1RMbdgDmhgpm3VaOu2+fiS/SfTpQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.9.0 <1.10.0' + '@opentelemetry/sdk-trace-base@1.30.1': resolution: {integrity: sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/sdk-trace-base@2.6.1': + resolution: {integrity: sha512-r86ut4T1e8vNwB35CqCcKd45yzqH6/6Wzvpk2/cZB8PsPLlZFTvrh8yfOS3CYZYcUmAx4hHTZJ8AO8Dj8nrdhw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/sdk-trace-node@1.30.1': resolution: {integrity: sha512-cBjYOINt1JxXdpw1e5MlHmFRc5fgj4GW/86vsKFxJCJ8AL4PdVtYH41gWwl4qd4uQjqEL1oJVrXkSy5cnduAnQ==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/sdk-trace-node@2.6.1': + resolution: {integrity: sha512-Hh2i4FwHWRFhnO2Q/p6svMxy8MPsNCG0uuzUY3glqm0rwM0nQvbTO1dXSp9OqQoTKXcQzaz9q1f65fsurmOhNw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/semantic-conventions@1.28.0': resolution: {integrity: sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==} engines: {node: '>=14'} + '@opentelemetry/semantic-conventions@1.40.0': + resolution: {integrity: sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==} + engines: {node: '>=14'} + '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} @@ -1932,9 +2020,71 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.5': + resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.1': + resolution: {integrity: sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.2': + resolution: {integrity: sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.1': + resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} + '@quansync/fs@1.0.0': resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} + '@redocly/ajv@8.11.2': + resolution: {integrity: sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==} + + '@redocly/ajv@8.18.1': + resolution: {integrity: sha512-Ifm/pP/tul1qmAecpbVxCBluVE32rKfjf8gYXH4xI2gCv9mRWFhJMHzkPDM4TXlxwPQYIFegymlsy8lXz7optA==} + + '@redocly/cli-otel@0.3.1': + resolution: {integrity: sha512-TbC4bK2zLtU/O9I2pszHPP0rtJOvFhQmEwQ/FHxERPu71fgKG8POUDP2jSiGmsXE7NdGSHBKqnf+y9Acn2jq5g==} + + '@redocly/cli@2.31.2': + resolution: {integrity: sha512-MqO0I6UvB4d7VOTOrYAbVwS+AgUZ4Bxp7d2vCbUseiEYGxArvkzXtwWNLfNKryXvUrVB8kfmvLuRp7LLHFvvDA==} + engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'} + hasBin: true + + '@redocly/config@0.22.0': + resolution: {integrity: sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ==} + + '@redocly/config@0.48.2': + resolution: {integrity: sha512-DUHthTRdj+caAQWCtJae4yzvxaUDuwQkFsZFVaAEyORd8Bt8K2wYso61jYZuR/kQZaDejfUREtQTVVZ5VYTqgw==} + + '@redocly/openapi-core@1.34.14': + resolution: {integrity: sha512-y+xFx+Zz54Xhr8jUdnLENYnt7Y7GEDL6Q03ga7rTtX8DVwefX9H+hQEPgJp1nda7vdH+wJ9/HBVvyfBuW9x6rA==} + engines: {node: '>=18.17.0', npm: '>=9.5.0'} + + '@redocly/openapi-core@2.31.2': + resolution: {integrity: sha512-qKXAdKTRKqWArIWbMOHOELJGgfISMFD5pK0w5CaklH8LAn5M6BbyCocqz52IqMMUIiEyAsqb46a4vtuqPhLZwg==} + engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'} + + '@redocly/respect-core@2.31.2': + resolution: {integrity: sha512-M5zQV9M8uazCl46EVKKjWPo7M8EFNHFQOdovhqH+IfdAop5kHPi1fR1xSwrckak84XON0a+CqPU7z7+YCON0Bg==} + engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'} + '@replit/codemirror-css-color-picker@6.3.0': resolution: {integrity: sha512-19biDANghUm7Fz7L1SNMIhK48tagaWuCOHj4oPPxc7hxPGkTVY2lU/jVZ8tsbTKQPVG7BO2CBDzs7CBwb20t4A==} peerDependencies: @@ -2443,6 +2593,9 @@ packages: '@types/js-yaml@4.0.9': resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} @@ -3228,6 +3381,12 @@ packages: peerDependencies: ajv: 4.11.8 - 8 + better-ajv-errors@2.0.3: + resolution: {integrity: sha512-t1vxUP+vYKsaYi/BbKo2K98nEAZmfi4sjwvmRT8aOPDzPJeAtLurfoIDazVkLILxO4K+Sw4YrLYnBQ46l6pePg==} + engines: {node: '>= 18.20.6'} + peerDependencies: + ajv: 4.11.8 - 8 + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -3318,6 +3477,9 @@ packages: resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} + call-me-maybe@1.0.2: + resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} + callsite@1.0.0: resolution: {integrity: sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==} @@ -3389,6 +3551,9 @@ packages: cjs-module-lexer@1.4.3: resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + classnames@2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + clean-css@5.3.3: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} engines: {node: '>= 10.0'} @@ -3421,6 +3586,9 @@ packages: resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} engines: {node: '>= 10'} + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -3459,6 +3627,9 @@ packages: resolution: {integrity: sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==} engines: {node: '>=18'} + colorette@1.4.0: + resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} + colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -3550,6 +3721,9 @@ packages: resolution: {integrity: sha512-X8XDzyvYaA6msMyAM575CUoygY5b44QzLcGRKsK3MFmXcOvQa518dNPLsKYwkYsn72g3EiW+LE0ytd/FlqWmyw==} engines: {node: '>=18'} + core-js@3.49.0: + resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -3668,6 +3842,9 @@ packages: decache@4.6.2: resolution: {integrity: sha512-2LPqkLeu8XWHU8qNCS3kcF6sCcb5zIzvWaAHYSvPfwhdd7mHuah29NssMzrTYyHN4F5oFy2ko9OBYxegtU0FEw==} + decko@1.2.0: + resolution: {integrity: sha512-m8FnyHXV1QX+S1cl+KPFDIl6NMkxtKsy6+U/aYyjrOqWMuwAwYWu7ePqrsUHtDR5Y8Yk2pi/KIDSgF+vT4cPOQ==} + decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} @@ -3830,6 +4007,10 @@ packages: resolution: {integrity: sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==} engines: {node: '>=18'} + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} + dotenv@16.6.1: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} @@ -3965,6 +4146,9 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} + es6-promise@3.3.1: + resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} + esast-util-from-estree@2.0.0: resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} @@ -4259,6 +4443,9 @@ packages: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} + foreach@2.0.6: + resolution: {integrity: sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==} + foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} @@ -4426,6 +4613,11 @@ packages: h3@1.15.11: resolution: {integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==} + handlebars@4.7.9: + resolution: {integrity: sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==} + engines: {node: '>=0.4.7'} + hasBin: true + has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} @@ -4590,6 +4782,9 @@ packages: resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + http2-client@1.3.5: + resolution: {integrity: sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==} + https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} @@ -4978,6 +5173,10 @@ packages: js-image-generator@1.0.4: resolution: {integrity: sha512-ckb7kyVojGAnArouVR+5lBIuwU1fcrn7E/YYSd0FK7oIngAkMmRvHASLro9Zt5SQdWToaI66NybG+OGxPw/HlQ==} + js-levenshtein@1.1.6: + resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==} + engines: {node: '>=0.10.0'} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -4990,9 +5189,16 @@ packages: engines: {node: '>=6'} hasBin: true + json-pointer@0.6.2: + resolution: {integrity: sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==} + json-schema-ref-resolver@3.0.0: resolution: {integrity: sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==} + json-schema-to-ts@2.7.2: + resolution: {integrity: sha512-R1JfqKqbBR4qE8UyBR56Ms30LL62/nlhoz+1UkfI/VE7p54Awu919FZ6ZUPG8zIa3XB65usPJgr1ONVncUGSaQ==} + engines: {node: '>=16'} + json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} @@ -5013,6 +5219,10 @@ packages: jsonc-parser@3.3.1: resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + jsonpath-rfc9535@1.3.0: + resolution: {integrity: sha512-3jFHya7oZ45aDxIIdx+/zQARahHXxFSMWBkcBUldfXpLS9VCXDJyTKt35kQfEXLqh0K3Ixw/9xFnvcDStaxh7Q==} + engines: {node: '>=20'} + jsonpointer@5.0.1: resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} engines: {node: '>=0.10.0'} @@ -5216,9 +5426,16 @@ packages: resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} engines: {node: '>= 12.0.0'} + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} @@ -5235,6 +5452,9 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lunr@2.3.9: + resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + luxon@3.7.2: resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} engines: {node: '>=12'} @@ -5264,6 +5484,9 @@ packages: resolution: {integrity: sha512-K6K2NgKnTXimT3779/4KxSvobxOtMmx1LBZ3NwRxT/MDIR3Br/fQ4Q+WCX5QxjyUR8zg5+RV9Tbf2c5pAWTD2A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + mark.js@8.11.1: + resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} + markdown-extensions@2.0.0: resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} engines: {node: '>=16'} @@ -5301,6 +5524,11 @@ packages: engines: {node: '>= 20'} hasBin: true + marked@4.3.0: + resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} + engines: {node: '>= 12'} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -5558,6 +5786,35 @@ packages: mlly@1.8.2: resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} + mobx-react-lite@4.1.1: + resolution: {integrity: sha512-iUxiMpsvNraCKXU+yPotsOncNNmyeS2B5DKL+TL6Tar/xm+wwNJAubJmtRSeAoYawdZqwv8Z/+5nPRHeQxTiXg==} + peerDependencies: + mobx: ^6.9.0 + react: ^16.8.0 || ^17 || ^18 || ^19 + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + + mobx-react@9.2.0: + resolution: {integrity: sha512-dkGWCx+S0/1mfiuFfHRH8D9cplmwhxOV5CkXMp38u6rQGG2Pv3FWYztS0M7ncR6TyPRQKaTG/pnitInoYE9Vrw==} + peerDependencies: + mobx: ^6.9.0 + react: ^16.8.0 || ^17 || ^18 || ^19 + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + + mobx@6.15.3: + resolution: {integrity: sha512-6+ZSYDs5zgH5CdGfEU2q2Lsa5PztVryL1ys7kAImTU25n2A9LAMj/yneVsQpd03MfwMLDQF+7kakJR9Z+cQxSw==} + modern-tar@0.7.5: resolution: {integrity: sha512-YTefgdpKKFgoTDbEUqXqgUJct2OG6/4hs4XWLsxcHkDLj/x/V8WmKIRppPnXP5feQ7d1vuYWSp3qKkxfwaFaxA==} engines: {node: '>=18.0.0'} @@ -5637,6 +5894,9 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + neotraverse@0.6.18: resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} engines: {node: '>= 10'} @@ -5672,6 +5932,10 @@ packages: resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==} engines: {node: '>= 0.4'} + node-fetch-h2@2.3.0: + resolution: {integrity: sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==} + engines: {node: 4.x || >=6.0.0} + node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} @@ -5699,6 +5963,9 @@ packages: node-mock-http@1.0.4: resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} + node-readfiles@0.2.0: + resolution: {integrity: sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==} + node-releases@2.0.37: resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==} @@ -5750,6 +6017,26 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + oas-kit-common@1.0.8: + resolution: {integrity: sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==} + + oas-linter@3.2.2: + resolution: {integrity: sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==} + + oas-resolver@2.5.6: + resolution: {integrity: sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==} + hasBin: true + + oas-schema-walker@1.1.5: + resolution: {integrity: sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==} + + oas-validator@5.0.8: + resolution: {integrity: sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} @@ -5826,6 +6113,9 @@ packages: resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==} engines: {node: '>=20'} + openapi-sampler@1.7.3: + resolution: {integrity: sha512-Qgy2+Z7xR3l7kXurtzi1PCtzAINkFKhBADBe/8cidC2fQrLUQTudLiJjQDnqJXoisWAR6zaHhC0hP6Hn5vja+g==} + ora@5.4.1: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} @@ -5834,6 +6124,9 @@ packages: resolution: {integrity: sha512-zBd1G8HkewNd2A8oQ8c6BN/f/c9EId7rSUueOLGu28govmUctXmM+3765GwsByv9nYUdrLqHphXlYIc86saYsg==} engines: {node: '>=18'} + outdent@0.8.0: + resolution: {integrity: sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==} + own-keys@1.0.1: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} @@ -6006,6 +6299,9 @@ packages: perfect-debounce@2.1.0: resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==} + perfect-scrollbar@1.5.6: + resolution: {integrity: sha512-rixgxw3SxyJbCaSpo1n35A/fwI1r2rdwMKOTCg/AcG+xOEyZcE8UHVjpZMFCVImzsFoCZeJTT+M/rdEIQYO2nw==} + pg-cloudflare@1.3.0: resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==} @@ -6076,6 +6372,14 @@ packages: pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + polished@4.3.1: + resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} + engines: {node: '>=10'} + possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -6225,12 +6529,19 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + protobufjs@7.6.0: + resolution: {integrity: sha512-LtESOsMPTZgyYtwxhvdgdjGL0HmXEaRA/hVD6sol4zA60hVXXXP/SGmxnqDbgGE8gy7pYex7cym+5vYPcmaXBQ==} + engines: {node: '>=12.0.0'} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -6280,6 +6591,9 @@ packages: resolution: {integrity: sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==} engines: {node: '>= 0.8'} + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -6297,10 +6611,18 @@ packages: peerDependencies: react: ^19.2.5 + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-refresh@0.18.0: resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} engines: {node: '>=0.10.0'} + react-tabs@6.1.1: + resolution: {integrity: sha512-CPiuKoMFf89B7QlbFfdBD9XmUWiE3qudQputMVZB8GQvPJZRX/gqjDaDWOPDwGinEfpJKEuBCkGt83Tt4efeyA==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 + react@19.2.5: resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==} engines: {node: '>=0.10.0'} @@ -6365,10 +6687,23 @@ packages: recma-stringify@1.0.0: resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + redoc@2.5.1: + resolution: {integrity: sha512-LmqA+4A3CmhTllGG197F0arUpmChukAj9klfSdxNRemT9Hr07xXr7OGKu4PHzBs359sgrJ+4JwmOlM7nxLPGMg==} + engines: {node: '>=6.9', npm: '>=3.0.0'} + peerDependencies: + core-js: ^3.1.4 + mobx: ^6.0.4 + react: ^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0 + styled-components: ^4.1.1 || ^5.1.1 || ^6.0.5 + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} + reftools@1.1.9: + resolution: {integrity: sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==} + regex-recursion@6.0.2: resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} @@ -6687,6 +7022,24 @@ packages: resolution: {integrity: sha512-eAVKTMedR5ckPo4xne/PjYQYrU3qx78gtJZ+sHlXEg5IHhhoQhMfZVzetTYuaJS0L2Ef3AcCRzCHV8T0WI6nIQ==} engines: {node: '>=20'} + should-equal@2.0.0: + resolution: {integrity: sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==} + + should-format@3.0.3: + resolution: {integrity: sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==} + + should-type-adaptors@1.1.0: + resolution: {integrity: sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==} + + should-type@1.4.0: + resolution: {integrity: sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==} + + should-util@1.0.1: + resolution: {integrity: sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==} + + should@13.2.3: + resolution: {integrity: sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==} + side-channel-list@1.0.1: resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} engines: {node: '>= 0.4'} @@ -6714,6 +7067,9 @@ packages: resolution: {integrity: sha512-WszCLXwT4h2k1ufIXAgsbiTOazqqevFCIncOuUBZJ91DdvWcC5+OFkluWRQPrcuSYd8fjq+o2y1QfWqYMoAToQ==} hasBin: true + simple-websocket@9.1.0: + resolution: {integrity: sha512-8MJPnjRN6A8UCp1I+H/dSFyjwJhp6wta4hsVRhjf8w9qBHRzxYt14RaOcjvQnhD1N4yKOddEjflwMnQM4VtXjQ==} + sirv@3.0.2: resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} engines: {node: '>=18'} @@ -6737,6 +7093,10 @@ packages: resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} engines: {node: '>=20'} + slugify@1.4.7: + resolution: {integrity: sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg==} + engines: {node: '>=8.0.0'} + smartypants@0.2.2: resolution: {integrity: sha512-TzobUYoEft/xBtb2voRPryAUIvYguG0V7Tt3de79I1WfXgCwelqVsGuZSnu3GFGRZhXR90AeEYIM+icuB/S06Q==} hasBin: true @@ -6893,6 +7253,9 @@ packages: std-env@4.1.0: resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + stickyfill@1.1.1: + resolution: {integrity: sha512-GCp7vHAfpao+Qh/3Flh9DXEJ/qSi0KJwJw6zYlZOtRYXWUIpMM6mC2rIep/dK8RQqwW0KxGJIllmjPIBOGN8AA==} + stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -6986,6 +7349,25 @@ packages: style-to-object@1.0.14: resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} + styled-components@6.4.1: + resolution: {integrity: sha512-ADu2dF53esUzzM4I0ewxhxFtsDd6v4V6dNkg3vG0iFKhnt06sJneTZnRvujAosZwW0XD58IKgGMQoqri4wHRqg==} + engines: {node: '>= 16'} + peerDependencies: + css-to-react-native: '>= 3.2.0' + react: '>= 16.8.0' + react-dom: '>= 16.8.0' + react-native: '>= 0.68.0' + peerDependenciesMeta: + css-to-react-native: + optional: true + react-dom: + optional: true + react-native: + optional: true + + stylis@4.3.6: + resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} + suf-log@2.5.3: resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==} @@ -7018,6 +7400,10 @@ packages: engines: {node: '>=16'} hasBin: true + swagger2openapi@7.0.8: + resolution: {integrity: sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==} + hasBin: true + swrv@1.2.0: resolution: {integrity: sha512-lH/g4UcNyj+7lzK4eRGT4C68Q4EhQ6JtM9otPRIASfhhzfLWtbZPHcMuhuba7S9YVYuxkMUGImwMyGpfbkH07A==} peerDependencies: @@ -7149,6 +7535,9 @@ packages: resolution: {integrity: sha512-QVsbr1WhGLq2F0oDyYbqtOXcf3gcnL8C9H5EX8bBwAr8ZWvWGJzukpPrDrWgJMrNtgDbo74BIjI4kJu3q2xQWw==} engines: {node: '>=18.18.0'} + ts-algebra@1.2.2: + resolution: {integrity: sha512-kloPhf1hq3JbCPOTYoOWDKxebWjNb2o/LKnNfkWhxVVisFFmMJPPdJeGoGmM+iRLyoXAR61e08Pb+vUXINg8aA==} + ts-api-utils@2.5.0: resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} @@ -7244,10 +7633,19 @@ packages: ufo@1.6.3: resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + uid-safe@2.1.5: resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==} engines: {node: '>= 0.8'} + ulid@2.4.0: + resolution: {integrity: sha512-fIRiVTJNcSRmXKPZtGzFQv9WRrZ3M9eoptl/teFJvjOzmpU+/K/JH6HZ8deBfb5vMEpicJcLn7JmvdknlMq7Zg==} + hasBin: true + ulid@3.0.1: resolution: {integrity: sha512-dPJyqPzx8preQhqq24bBG1YNkvigm87K8kVEHCD+ruZg24t6IFEFv00xMWfxcC4djmFtiTLdFuADn4+DOz6R7Q==} hasBin: true @@ -7278,6 +7676,10 @@ packages: undici-types@7.19.2: resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} + undici@6.24.0: + resolution: {integrity: sha512-lVLNosgqo5EkGqh5XUDhGfsMSoO8K0BAN0TyJLvwNRSl4xWGZlCVYsAIpa/OpA3TvmnM01GWcoKmc3ZWo5wKKA==} + engines: {node: '>=18.17'} + unhead@2.1.13: resolution: {integrity: sha512-jO9M1sI6b2h/1KpIu4Jeu+ptumLmUKboRRLxys5pYHFeT+lqTzfNHbYUX9bxVDhC1FBszAGuWcUVlmvIPsah8Q==} @@ -7478,12 +7880,23 @@ packages: uqr@0.1.3: resolution: {integrity: sha512-0rjE8iEJe4YmT9TOhwsZtqCMRLc5DXZUI2UEYUUg63ikBkqqE5EYWaI0etFe/5KUcmcYwLih2RND1kq+hrUJXA==} + uri-js-replace@1.0.1: + resolution: {integrity: sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==} + + url-template@2.0.8: + resolution: {integrity: sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==} + urlpattern-polyfill@10.1.0: resolution: {integrity: sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==} urlpattern-polyfill@8.0.2: resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==} + use-sync-external-store@1.6.0: + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -7817,6 +8230,9 @@ packages: resolution: {integrity: sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==} engines: {node: '>= 12.0.0'} + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + wrap-ansi@10.0.0: resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==} engines: {node: '>=20'} @@ -7840,6 +8256,18 @@ packages: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + ws@8.19.0: resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} engines: {node: '>=10.0.0'} @@ -7887,10 +8315,17 @@ packages: resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} engines: {node: '>=18'} + yaml-ast-parser@0.0.43: + resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==} + yaml-language-server@1.20.0: resolution: {integrity: sha512-qhjK/bzSRZ6HtTvgeFvjNPJGWdZ0+x5NREV/9XZWFjIGezew2b4r5JPy66IfOhd5OA7KeFwk1JfmEbnTvev0cA==} hasBin: true + yaml@1.10.3: + resolution: {integrity: sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==} + engines: {node: '>= 6'} + yaml@2.7.1: resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} engines: {node: '>= 14'} @@ -7901,6 +8336,10 @@ packages: engines: {node: '>= 14.6'} hasBin: true + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -7909,6 +8348,10 @@ packages: resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yargs@17.0.1: + resolution: {integrity: sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==} + engines: {node: '>=12'} + yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} @@ -8668,6 +9111,12 @@ snapshots: tslib: 2.8.1 optional: true + '@emotion/is-prop-valid@1.4.0': + dependencies: + '@emotion/memoize': 0.9.0 + + '@emotion/memoize@0.9.0': {} + '@envelop/instrumentation@1.0.0': dependencies: '@whatwg-node/promise-helpers': 1.3.2 @@ -8831,6 +9280,8 @@ snapshots: '@esbuild/win32-x64@0.27.7': optional: true + '@exodus/schemasafe@1.3.0': {} + '@expressive-code/core@0.41.7': dependencies: '@ctrl/tinycolor': 4.2.0 @@ -8864,6 +9315,8 @@ snapshots: dependencies: '@expressive-code/core': 0.41.7 + '@faker-js/faker@7.6.0': {} + '@fastify/accept-negotiator@2.0.1': {} '@fastify/ajv-compiler@4.0.5': @@ -9828,6 +10281,8 @@ snapshots: - rollup - supports-color + '@noble/hashes@1.8.0': {} + '@nodable/entities@1.1.0': {} '@nodelib/fs.scandir@2.1.5': @@ -10023,6 +10478,10 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs@0.214.0': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api@1.8.0': {} '@opentelemetry/api@1.9.0': {} @@ -10033,11 +10492,29 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.28.0 + '@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/exporter-trace-otlp-http@0.214.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation@0.203.0(@opentelemetry/api@1.9.0)(supports-color@10.2.2)': dependencies: '@opentelemetry/api': 1.9.0 @@ -10047,6 +10524,23 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/otlp-exporter-base@0.214.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.214.0(@opentelemetry/api@1.9.1) + + '@opentelemetry/otlp-transformer@0.214.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.214.0 + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.1) + protobufjs: 7.6.0 + '@opentelemetry/propagator-b3@1.30.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -10063,6 +10557,26 @@ snapshots: '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.28.0 + '@opentelemetry/resources@2.6.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/sdk-logs@0.214.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.214.0 + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + + '@opentelemetry/sdk-metrics@2.6.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -10070,6 +10584,13 @@ snapshots: '@opentelemetry/resources': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.28.0 + '@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sdk-trace-node@1.30.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -10080,8 +10601,17 @@ snapshots: '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) semver: 7.7.4 + '@opentelemetry/sdk-trace-node@2.6.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/context-async-hooks': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions@1.28.0': {} + '@opentelemetry/semantic-conventions@1.40.0': {} + '@oslojs/encoding@1.1.0': {} '@pagefind/darwin-arm64@1.5.2': @@ -10201,10 +10731,138 @@ snapshots: '@polka/url@1.0.0-next.29': {} + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.5': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.1': + dependencies: + '@protobufjs/aspromise': 1.1.2 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.2': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.1': {} + '@quansync/fs@1.0.0': dependencies: quansync: 1.0.0 + '@redocly/ajv@8.11.2': + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js-replace: 1.0.1 + + '@redocly/ajv@8.18.1': + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + '@redocly/cli-otel@0.3.1': + dependencies: + ulid: 2.4.0 + + '@redocly/cli@2.31.2(@opentelemetry/api@1.9.1)(core-js@3.49.0)': + dependencies: + '@opentelemetry/exporter-trace-otlp-http': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-node': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@redocly/cli-otel': 0.3.1 + '@redocly/openapi-core': 2.31.2 + '@redocly/respect-core': 2.31.2 + ajv: '@redocly/ajv@8.18.1' + ajv-formats: 3.0.1(@redocly/ajv@8.18.1) + colorette: 1.4.0 + cookie: 0.7.2 + dotenv: 16.4.7 + glob: 11.1.0 + handlebars: 4.7.9 + https-proxy-agent: 7.0.6(supports-color@10.2.2) + mobx: 6.15.3 + picomatch: 4.0.4 + pluralize: 8.0.0 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + redoc: 2.5.1(core-js@3.49.0)(mobx@6.15.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(styled-components@6.4.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)) + semver: 7.7.4 + set-cookie-parser: 2.7.2 + simple-websocket: 9.1.0 + styled-components: 6.4.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + ulid: 3.0.2 + undici: 6.24.0 + yargs: 17.0.1 + transitivePeerDependencies: + - '@opentelemetry/api' + - bufferutil + - core-js + - css-to-react-native + - encoding + - react-native + - supports-color + - utf-8-validate + + '@redocly/config@0.22.0': {} + + '@redocly/config@0.48.2': + dependencies: + json-schema-to-ts: 2.7.2 + + '@redocly/openapi-core@1.34.14': + dependencies: + '@redocly/ajv': 8.11.2 + '@redocly/config': 0.22.0 + colorette: 1.4.0 + https-proxy-agent: 7.0.6(supports-color@10.2.2) + js-levenshtein: 1.1.6 + js-yaml: 4.1.1 + minimatch: 5.1.9 + pluralize: 8.0.0 + yaml-ast-parser: 0.0.43 + transitivePeerDependencies: + - supports-color + + '@redocly/openapi-core@2.31.2': + dependencies: + '@redocly/ajv': 8.18.1 + '@redocly/config': 0.48.2 + ajv: '@redocly/ajv@8.18.1' + ajv-formats: 3.0.1(@redocly/ajv@8.18.1) + colorette: 1.4.0 + js-levenshtein: 1.1.6 + js-yaml: 4.1.1 + picomatch: 4.0.4 + pluralize: 8.0.0 + yaml-ast-parser: 0.0.43 + + '@redocly/respect-core@2.31.2': + dependencies: + '@faker-js/faker': 7.6.0 + '@noble/hashes': 1.8.0 + '@redocly/ajv': 8.18.1 + '@redocly/openapi-core': 2.31.2 + ajv: '@redocly/ajv@8.18.1' + better-ajv-errors: 2.0.3(@redocly/ajv@8.18.1) + colorette: 2.0.20 + json-pointer: 0.6.2 + jsonpath-rfc9535: 1.3.0 + openapi-sampler: 1.7.3 + outdent: 0.8.0 + picomatch: 4.0.4 + '@replit/codemirror-css-color-picker@6.3.0(@codemirror/language@6.12.3)(@codemirror/state@6.6.0)(@codemirror/view@6.41.0)': dependencies: '@codemirror/language': 6.12.3 @@ -10886,6 +11544,8 @@ snapshots: '@types/js-yaml@4.0.9': {} + '@types/json-schema@7.0.15': {} + '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 @@ -11582,6 +12242,10 @@ snapshots: dependencies: ajv: 8.18.0 + ajv-formats@3.0.1(@redocly/ajv@8.18.1): + optionalDependencies: + ajv: '@redocly/ajv@8.18.1' + ajv-formats@3.0.1(ajv@8.18.0): optionalDependencies: ajv: 8.18.0 @@ -11929,6 +12593,15 @@ snapshots: jsonpointer: 5.0.1 leven: 3.1.0 + better-ajv-errors@2.0.3(@redocly/ajv@8.18.1): + dependencies: + '@babel/code-frame': 7.29.0 + '@humanwhocodes/momoa': 2.0.4 + ajv: '@redocly/ajv@8.18.1' + chalk: 4.1.2 + jsonpointer: 5.0.1 + leven: 3.1.0 + binary-extensions@2.3.0: {} bindings@1.5.0: @@ -12037,6 +12710,8 @@ snapshots: call-bind-apply-helpers: 1.0.2 get-intrinsic: 1.3.0 + call-me-maybe@1.0.2: {} + callsite@1.0.0: {} camel-case@4.1.2: @@ -12103,6 +12778,8 @@ snapshots: cjs-module-lexer@1.4.3: {} + classnames@2.5.1: {} + clean-css@5.3.3: dependencies: source-map: 0.6.1 @@ -12131,6 +12808,12 @@ snapshots: cli-width@3.0.0: {} + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -12164,6 +12847,8 @@ snapshots: color-convert: 3.1.3 color-string: 2.1.4 + colorette@1.4.0: {} + colorette@2.0.20: {} colors@1.4.0: {} @@ -12234,6 +12919,8 @@ snapshots: graceful-fs: 4.2.11 p-event: 6.0.1 + core-js@3.49.0: {} + core-util-is@1.0.3: {} cpy@11.1.0: @@ -12347,6 +13034,8 @@ snapshots: dependencies: callsite: 1.0.0 + decko@1.2.0: {} + decode-named-character-reference@1.3.0: dependencies: character-entities: 2.0.2 @@ -12505,6 +13194,8 @@ snapshots: dependencies: type-fest: 4.41.0 + dotenv@16.4.7: {} + dotenv@16.6.1: {} dotenv@17.3.1: {} @@ -12668,6 +13359,8 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + es6-promise@3.3.1: {} + esast-util-from-estree@2.0.0: dependencies: '@types/estree-jsx': 1.0.5 @@ -13076,6 +13769,8 @@ snapshots: dependencies: is-callable: 1.2.7 + foreach@2.0.6: {} + foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 @@ -13241,6 +13936,15 @@ snapshots: ufo: 1.6.3 uncrypto: 0.1.3 + handlebars@4.7.9: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 + has-bigints@1.1.0: {} has-flag@4.0.0: {} @@ -13562,6 +14266,8 @@ snapshots: http-shutdown@1.2.2: {} + http2-client@1.3.5: {} + https-proxy-agent@7.0.6(supports-color@10.2.2): dependencies: agent-base: 7.1.4 @@ -13975,6 +14681,8 @@ snapshots: dependencies: jpeg-js: 0.4.4 + js-levenshtein@1.1.6: {} + js-tokens@4.0.0: {} js-yaml@4.1.1: @@ -13983,10 +14691,20 @@ snapshots: jsesc@3.1.0: {} + json-pointer@0.6.2: + dependencies: + foreach: 2.0.6 + json-schema-ref-resolver@3.0.0: dependencies: dequal: 2.0.3 + json-schema-to-ts@2.7.2: + dependencies: + '@babel/runtime': 7.29.2 + '@types/json-schema': 7.0.15 + ts-algebra: 1.2.2 + json-schema-traverse@1.0.0: {} json-schema@0.4.0: {} @@ -13999,6 +14717,8 @@ snapshots: jsonc-parser@3.3.1: {} + jsonpath-rfc9535@1.3.0: {} + jsonpointer@5.0.1: {} jsonwebtoken@9.0.3: @@ -14202,8 +14922,14 @@ snapshots: safe-stable-stringify: 2.5.0 triple-beam: 1.4.1 + long@5.3.2: {} + longest-streak@3.1.0: {} + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + lower-case@2.0.2: dependencies: tslib: 2.8.1 @@ -14222,6 +14948,8 @@ snapshots: dependencies: yallist: 3.1.1 + lunr@2.3.9: {} + luxon@3.7.2: {} macos-release@3.4.0: {} @@ -14250,6 +14978,8 @@ snapshots: map-obj@5.0.2: {} + mark.js@8.11.1: {} + markdown-extensions@2.0.0: {} markdown-table@3.0.4: {} @@ -14273,6 +15003,8 @@ snapshots: marked@17.0.6: {} + marked@4.3.0: {} + math-intrinsics@1.1.0: {} maxstache-stream@1.0.4: @@ -14808,6 +15540,24 @@ snapshots: pkg-types: 1.3.1 ufo: 1.6.3 + mobx-react-lite@4.1.1(mobx@6.15.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + dependencies: + mobx: 6.15.3 + react: 19.2.5 + use-sync-external-store: 1.6.0(react@19.2.5) + optionalDependencies: + react-dom: 19.2.5(react@19.2.5) + + mobx-react@9.2.0(mobx@6.15.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + dependencies: + mobx: 6.15.3 + mobx-react-lite: 4.1.1(mobx@6.15.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + optionalDependencies: + react-dom: 19.2.5(react@19.2.5) + + mobx@6.15.3: {} + modern-tar@0.7.5: {} module-definition@6.0.1: @@ -14886,6 +15636,8 @@ snapshots: negotiator@1.0.0: {} + neo-async@2.6.2: {} + neotraverse@0.6.18: {} netlify-cli@25.3.0(@types/node@25.6.0)(picomatch@4.0.4)(rollup@4.60.1): @@ -15049,6 +15801,10 @@ snapshots: object.entries: 1.1.9 semver: 6.3.1 + node-fetch-h2@2.3.0: + dependencies: + http2-client: 1.3.5 + node-fetch-native@1.6.7: {} node-fetch@2.7.0: @@ -15067,6 +15823,10 @@ snapshots: node-mock-http@1.0.4: {} + node-readfiles@0.2.0: + dependencies: + es6-promise: 3.3.1 + node-releases@2.0.37: {} node-source-walk@7.0.1: @@ -15120,6 +15880,39 @@ snapshots: dependencies: boolbase: 1.0.0 + oas-kit-common@1.0.8: + dependencies: + fast-safe-stringify: 2.1.1 + + oas-linter@3.2.2: + dependencies: + '@exodus/schemasafe': 1.3.0 + should: 13.2.3 + yaml: 1.10.3 + + oas-resolver@2.5.6: + dependencies: + node-fetch-h2: 2.3.0 + oas-kit-common: 1.0.8 + reftools: 1.1.9 + yaml: 1.10.3 + yargs: 17.7.2 + + oas-schema-walker@1.1.5: {} + + oas-validator@5.0.8: + dependencies: + call-me-maybe: 1.0.2 + oas-kit-common: 1.0.8 + oas-linter: 3.2.2 + oas-resolver: 2.5.6 + oas-schema-walker: 1.1.5 + reftools: 1.1.9 + should: 13.2.3 + yaml: 1.10.3 + + object-assign@4.1.1: {} + object-inspect@1.13.4: {} object-keys@1.1.1: {} @@ -15218,6 +16011,12 @@ snapshots: powershell-utils: 0.1.0 wsl-utils: 0.3.1 + openapi-sampler@1.7.3: + dependencies: + '@types/json-schema': 7.0.15 + fast-xml-parser: 5.6.0 + json-pointer: 0.6.2 + ora@5.4.1: dependencies: bl: 4.1.0 @@ -15235,6 +16034,8 @@ snapshots: macos-release: 3.4.0 windows-release: 6.1.0 + outdent@0.8.0: {} + own-keys@1.0.1: dependencies: get-intrinsic: 1.3.0 @@ -15404,6 +16205,8 @@ snapshots: perfect-debounce@2.1.0: {} + perfect-scrollbar@1.5.6: {} + pg-cloudflare@1.3.0: optional: true @@ -15483,6 +16286,12 @@ snapshots: exsolve: 1.0.8 pathe: 2.0.3 + pluralize@8.0.0: {} + + polished@4.3.1: + dependencies: + '@babel/runtime': 7.29.2 + possible-typed-array-names@1.1.0: {} postcss-nested@6.2.0(postcss@8.5.10): @@ -15586,10 +16395,31 @@ snapshots: process@0.11.10: {} + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + property-information@7.1.0: {} proto-list@1.2.4: {} + protobufjs@7.6.0: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.1 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.2 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.1 + '@types/node': 25.6.0 + long: 5.3.2 + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -15646,6 +16476,10 @@ snapshots: random-bytes@1.0.0: {} + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + range-parser@1.2.1: {} raw-body@3.0.1: @@ -15667,8 +16501,16 @@ snapshots: react: 19.2.5 scheduler: 0.27.0 + react-is@16.13.1: {} + react-refresh@0.18.0: {} + react-tabs@6.1.1(react@19.2.5): + dependencies: + clsx: 2.1.1 + prop-types: 15.8.1 + react: 19.2.5 + react@19.2.5: {} read-package-up@11.0.0: @@ -15766,6 +16608,39 @@ snapshots: unified: 11.0.5 vfile: 6.0.3 + redoc@2.5.1(core-js@3.49.0)(mobx@6.15.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(styled-components@6.4.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)): + dependencies: + '@redocly/openapi-core': 1.34.14 + classnames: 2.5.1 + core-js: 3.49.0 + decko: 1.2.0 + dompurify: 3.2.7 + eventemitter3: 5.0.4 + json-pointer: 0.6.2 + lunr: 2.3.9 + mark.js: 8.11.1 + marked: 4.3.0 + mobx: 6.15.3 + mobx-react: 9.2.0(mobx@6.15.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + openapi-sampler: 1.7.3 + path-browserify: 1.0.1 + perfect-scrollbar: 1.5.6 + polished: 4.3.1 + prismjs: 1.30.0 + prop-types: 15.8.1 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + react-tabs: 6.1.1(react@19.2.5) + slugify: 1.4.7 + stickyfill: 1.1.1 + styled-components: 6.4.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + swagger2openapi: 7.0.8 + url-template: 2.0.8 + transitivePeerDependencies: + - encoding + - react-native + - supports-color + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.9 @@ -15777,6 +16652,8 @@ snapshots: get-proto: 1.0.1 which-builtin-type: 1.2.1 + reftools@1.1.9: {} + regex-recursion@6.0.2: dependencies: regex-utilities: 2.3.0 @@ -16266,6 +17143,32 @@ snapshots: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 + should-equal@2.0.0: + dependencies: + should-type: 1.4.0 + + should-format@3.0.3: + dependencies: + should-type: 1.4.0 + should-type-adaptors: 1.1.0 + + should-type-adaptors@1.1.0: + dependencies: + should-type: 1.4.0 + should-util: 1.0.1 + + should-type@1.4.0: {} + + should-util@1.0.1: {} + + should@13.2.3: + dependencies: + should-equal: 2.0.0 + should-format: 3.0.3 + should-type: 1.4.0 + should-type-adaptors: 1.1.0 + should-util: 1.0.1 + side-channel-list@1.0.1: dependencies: es-errors: 1.3.0 @@ -16300,6 +17203,18 @@ snapshots: simple-git-hooks@2.13.1: {} + simple-websocket@9.1.0: + dependencies: + debug: 4.4.3(supports-color@10.2.2) + queue-microtask: 1.2.3 + randombytes: 2.1.0 + readable-stream: 3.6.2 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + sirv@3.0.2: dependencies: '@polka/url': 1.0.0-next.29 @@ -16324,6 +17239,8 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 + slugify@1.4.7: {} + smartypants@0.2.2: {} smol-toml@1.6.1: {} @@ -16522,6 +17439,8 @@ snapshots: std-env@4.1.0: {} + stickyfill@1.1.1: {} + stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -16634,6 +17553,17 @@ snapshots: dependencies: inline-style-parser: 0.2.7 + styled-components@6.4.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + dependencies: + '@emotion/is-prop-valid': 1.4.0 + csstype: 3.2.3 + react: 19.2.5 + stylis: 4.3.6 + optionalDependencies: + react-dom: 19.2.5(react@19.2.5) + + stylis@4.3.6: {} + suf-log@2.5.3: dependencies: s.color: 0.0.15 @@ -16672,6 +17602,22 @@ snapshots: picocolors: 1.1.1 sax: 1.6.0 + swagger2openapi@7.0.8: + dependencies: + call-me-maybe: 1.0.2 + node-fetch: 2.7.0 + node-fetch-h2: 2.3.0 + node-readfiles: 0.2.0 + oas-kit-common: 1.0.8 + oas-resolver: 2.5.6 + oas-schema-walker: 1.1.5 + oas-validator: 5.0.8 + reftools: 1.1.9 + yaml: 1.10.3 + yargs: 17.7.2 + transitivePeerDependencies: + - encoding + swrv@1.2.0(vue@3.5.33(typescript@6.0.3)): dependencies: vue: 3.5.33(typescript@6.0.3) @@ -16801,6 +17747,8 @@ snapshots: string-byte-length: 3.0.1 string-byte-slice: 3.0.1 + ts-algebra@1.2.2: {} + ts-api-utils@2.5.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -16900,10 +17848,15 @@ snapshots: ufo@1.6.3: {} + uglify-js@3.19.3: + optional: true + uid-safe@2.1.5: dependencies: random-bytes: 1.0.0 + ulid@2.4.0: {} + ulid@3.0.1: {} ulid@3.0.2: {} @@ -16936,6 +17889,8 @@ snapshots: undici-types@7.19.2: {} + undici@6.24.0: {} + unhead@2.1.13: dependencies: hookable: 6.1.1 @@ -17145,10 +18100,18 @@ snapshots: uqr@0.1.3: {} + uri-js-replace@1.0.1: {} + + url-template@2.0.8: {} + urlpattern-polyfill@10.1.0: {} urlpattern-polyfill@8.0.2: {} + use-sync-external-store@1.6.0(react@19.2.5): + dependencies: + react: 19.2.5 + util-deprecate@1.0.2: {} uuid@11.1.0: {} @@ -17509,6 +18472,8 @@ snapshots: triple-beam: 1.4.1 winston-transport: 4.9.0 + wordwrap@1.0.0: {} + wrap-ansi@10.0.0: dependencies: ansi-styles: 6.2.3 @@ -17540,6 +18505,8 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 4.1.0 + ws@7.5.10: {} + ws@8.19.0: {} wsl-utils@0.1.0: @@ -17568,6 +18535,8 @@ snapshots: yallist@5.0.0: {} + yaml-ast-parser@0.0.43: {} + yaml-language-server@1.20.0: dependencies: '@vscode/l10n': 0.0.18 @@ -17582,14 +18551,28 @@ snapshots: vscode-uri: 3.1.0 yaml: 2.7.1 + yaml@1.10.3: {} + yaml@2.7.1: {} yaml@2.8.3: {} + yargs-parser@20.2.9: {} + yargs-parser@21.1.1: {} yargs-parser@22.0.0: {} + yargs@17.0.1: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + yargs@17.7.2: dependencies: cliui: 8.0.1 diff --git a/public/api/agentkit.scalar.yaml b/public/api/agentkit.scalar.yaml new file mode 100644 index 000000000..8796a12b7 --- /dev/null +++ b/public/api/agentkit.scalar.yaml @@ -0,0 +1,1424 @@ +openapi: 3.1.1 +info: + title: AgentKit APIs + description: | + # Overview + + The AgentKit API gives your AI agents authenticated access to third-party apps — sending emails, reading calendars, creating tickets, querying databases, and more. Your agent calls a tool; Scalekit handles the OAuth flow, token storage, and API call. + + **Base URLs:** + + ``` + https://{your-subdomain}.scalekit.dev (Development) + https://{your-subdomain}.scalekit.com (Production) + ``` + + ## Quickstart + + ### 1. Get an access token + + Use your API credentials from the [Scalekit Dashboard](https://app.scalekit.com) → **Developers → Settings → API Credentials**. + + ```sh + curl -X POST https:///oauth/token \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + -d 'client_id={client_id}' \ + -d 'client_secret={client_secret}' \ + -d 'grant_type=client_credentials' + ``` + + ### 2. List connected accounts + + ```sh + curl https:///api/v1/connected_accounts \ + -H 'Authorization: Bearer {access_token}' + ``` + + ### 3. Execute a tool on behalf of a user + + ```sh + curl -X POST https:///api/v1/execute_tool \ + -H 'Authorization: Bearer {access_token}' \ + -H 'Content-Type: application/json' \ + -d '{ + "connected_account_id": "{connected_account_id}", + "tool_name": "gmail_fetch_emails", + "tool_input": { "max_results": 5 } + }' + ``` + + ## SDKs + + ```sh + npm install @scalekit-sdk/node # Node.js + pip install scalekit-sdk-python # Python + ``` + + For the full product guide, see the [AgentKit documentation](https://docs.scalekit.com/agentkit/quickstart/). + contact: + name: Scalekit Inc + url: https://scalekit.com + email: support@scalekit.com + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0 + version: 1.0.0 +servers: + - url: https://$SCALEKIT_ENVIRONMENT_URL +security: + - oauth2: [] +tags: + - description: Manage connected accounts for third-party integrations and OAuth connections. Connected accounts represent authenticated access to external services like Google, Notion, Slack, and other applications. + name: Connected Accounts +externalDocs: + description: AgentKit Docs + url: https://docs.scalekit.com/agentkit/quickstart/ +paths: + /api/v1/connected_accounts: + get: + description: Retrieves a paginated list of connected accounts for third-party integrations. Filter by organization, user, connector type, provider, or identifier. Returns OAuth tokens, API keys, and connection status for each account. Use pagination tokens to navigate through large result sets. + tags: + - Connected Accounts + summary: List connected accounts + operationId: ConnectedAccountService_ListConnectedAccounts + parameters: + - schema: + type: string + description: Filter by organization ID. Returns only connected accounts associated with this organization. + name: organization_id + in: query + - schema: + type: string + description: Filter by user ID. Returns only connected accounts associated with this user. + name: user_id + in: query + - schema: + type: string + description: Filter by connector type (e.g., 'notion', 'slack', 'google'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed. + name: connector + in: query + - schema: + type: string + description: Filter by account identifier. The unique identifier for the connected account within the third-party service (e.g., email address, workspace ID). + name: identifier + in: query + - schema: + type: string + description: Filter by OAuth provider. The authentication provider name such as 'google', 'microsoft', 'github', etc. + name: provider + in: query + - schema: + type: integer + format: int64 + description: Maximum number of connected accounts to return per page. Must be between 0 and 100. Default is typically 10. + name: page_size + in: query + - schema: + type: string + description: Pagination token from a previous response. Use the next_page_token value from ListConnectedAccountsResponse to fetch the next page. + name: page_token + in: query + - schema: + type: string + description: Text search query to filter connected accounts by name, identifier, or other searchable fields. Case-insensitive. + name: query + in: query + responses: + '200': + description: Successfully retrieved the list of connected accounts with their authentication details and status + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsListConnectedAccountsResponse' + '400': + description: Invalid request - occurs when query parameters are malformed or validation fails + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + put: + description: Updates authentication credentials and configuration for an existing connected account. Modify OAuth tokens, refresh tokens, access scopes, or API configuration settings. Specify the account by ID, or by combination of organization/user, connector, and identifier. Returns the updated account with new token expiry and status information. + tags: + - Connected Accounts + summary: Update connected account credentials + operationId: ConnectedAccountService_UpdateConnectedAccount + responses: + '200': + description: Connected account updated successfully with new credentials or configuration + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsUpdateConnectedAccountResponse' + '400': + description: Invalid request - missing required fields, invalid authorization details, or validation failed + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '404': + description: Connected account not found - the specified account does not exist + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsUpdateConnectedAccountRequest' + required: true + post: + description: Creates a new connected account with OAuth tokens or API credentials for third-party service integration. Supply authorization details including access tokens, refresh tokens, scopes, and optional API configuration. The account can be scoped to an organization or user. Returns the created account with its unique identifier and authentication status. + tags: + - Connected Accounts + summary: Create a connected account + operationId: ConnectedAccountService_CreateConnectedAccount + responses: + '201': + description: Connected account created successfully with authentication credentials stored securely + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsCreateConnectedAccountResponse' + '400': + description: Invalid request - missing required fields, invalid authorization details, or validation failed + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '409': + description: Conflict - connected account with the same identifier already exists + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsCreateConnectedAccountRequest' + required: true + /api/v1/connected_accounts/auth: + get: + description: Retrieves complete authentication details for a connected account including OAuth tokens, refresh tokens, scopes, and API configuration. Query by account ID or by combination of organization/user, connector, and identifier. Returns sensitive credential information - use appropriate access controls. + tags: + - Connected Accounts + summary: Get connected account auth credentials + operationId: ConnectedAccountService_GetConnectedAccountAuth + parameters: + - schema: + type: string + description: Organization ID for the connector + name: organization_id + in: query + - schema: + type: string + description: User ID for the connector + name: user_id + in: query + - schema: + type: string + description: Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed. + name: connector + in: query + - schema: + type: string + description: The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier). + name: identifier + in: query + - schema: + type: string + description: Unique identifier for the connected account + name: id + in: query + responses: + '200': + description: Successfully retrieved connected account with full authentication details + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsGetConnectedAccountByIdentifierResponse' + '400': + description: Invalid request - missing required query parameters + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '404': + description: Connected account not found - no account matches the specified criteria + content: + application/json: + schema: {} + /api/v1/connected_accounts/details: + get: + description: Returns metadata for a connected account including status, connector type, provider, and configuration without exposing stored authorization credentials. Look up by account ID, or by a combination of organization (or user), connector, and external identifier. + tags: + - Connected Accounts + summary: Get connected account metadata + operationId: ConnectedAccountService_GetConnectedAccountDetails + parameters: + - schema: + type: string + description: Organization ID for the connector + name: organization_id + in: query + - schema: + type: string + description: User ID for the connector + name: user_id + in: query + - schema: + type: string + description: Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed. + name: connector + in: query + - schema: + type: string + description: The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier). + name: identifier + in: query + - schema: + type: string + description: Unique identifier for the connected account + name: id + in: query + responses: + '200': + description: Successfully retrieved connected account details + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsGetConnectedAccountByIdentifierResponse' + '400': + description: Invalid request - missing required query parameters + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '404': + description: Connected account not found - no account matches the specified criteria + content: + application/json: + schema: {} + /api/v1/connected_accounts/magic_link: + post: + description: Creates a time-limited magic link for connecting or re-authorizing a third-party account. The link directs users to the OAuth authorization flow for the specified connector. Returns the generated link URL and expiration timestamp. Links typically expire after a short duration for security. + tags: + - Connected Accounts + summary: Generate authentication magic link + operationId: ConnectedAccountService_GetMagicLinkForConnectedAccount + responses: + '200': + description: Magic link generated successfully with authorization URL and expiry time + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsGetMagicLinkForConnectedAccountResponse' + '400': + description: Invalid request - missing required parameters or invalid connector + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsGetMagicLinkForConnectedAccountRequest' + required: true + /api/v1/connected_accounts/user/verify: + post: + description: Confirms the user assertion and activates the connected account after the user completes third-party OAuth. Called by the B2B app server with auth_request_id and identifier. Validates that the asserted identifier matches the one stored on the auth request and promotes pending tokens to live. + tags: + - Connected Accounts + summary: Verify connected account user + operationId: ConnectedAccountService_VerifyConnectedAccountUser + responses: + '200': + description: Verification successful; connected account is now ACTIVE + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsVerifyConnectedAccountUserResponse' + '400': + description: Invalid request - missing or malformed fields + content: + application/json: + schema: {} + '401': + description: Unauthorized - invalid or missing access token + content: + application/json: + schema: {} + '403': + description: Forbidden - identifier mismatch + content: + application/json: + schema: {} + '404': + description: Not found - no pending flow for the given auth_request_id or already consumed + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsVerifyConnectedAccountUserRequest' + required: true + /api/v1/connected_accounts:delete: + post: + description: Permanently removes a connected account and revokes all associated authentication credentials. Identify the account by ID, or by combination of organization/user, connector, and identifier. This action cannot be undone. All OAuth tokens and API keys for this account will be invalidated. + tags: + - Connected Accounts + summary: Delete a connected account + operationId: ConnectedAccountService_DeleteConnectedAccount + responses: + '200': + description: Connected account deleted successfully and all credentials revoked + content: + application/json: + schema: {} + '400': + description: Invalid request - malformed parameters or validation failed + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '404': + description: Connected account not found - the specified account does not exist + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsDeleteConnectedAccountRequest' + required: true + /api/v1/connected_accounts:search: + get: + description: Search for connected accounts in your environment using a text query that matches against identifiers, providers, or connectors. The search performs case-insensitive matching across account details. Returns paginated results with account status and authentication type information. + tags: + - Connected Accounts + summary: Search connected accounts + operationId: ConnectedAccountService_SearchConnectedAccounts + parameters: + - schema: + type: string + description: Search term to match against connected account identifiers, providers, or connectors. Must be at least 3 characters. Case insensitive. + name: query + in: query + - schema: + type: integer + format: int64 + description: Maximum number of connected accounts to return per page. Value must be between 1 and 30. + name: page_size + in: query + - schema: + type: string + description: Token from a previous response for pagination. Provide this to retrieve the next page of results. + name: page_token + in: query + - schema: + type: string + description: Connection ID to filter connected accounts + name: connection_id + in: query + responses: + '200': + description: Successfully retrieved matching connected accounts with pagination support + content: + application/json: + schema: + $ref: '#/components/schemas/connected_accountsSearchConnectedAccountsResponse' + '400': + description: Invalid request - query parameter is too short (minimum 3 characters) or validation failed + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + /api/v1/execute_tool: + post: + description: Executes a tool action using authentication credentials from a connected account. Specify the tool by name and provide required parameters as JSON. The connected account can be identified by ID, or by combination of organization/user, connector, and identifier. Returns the execution result data and a unique execution ID for tracking. Use this endpoint to perform actions like sending emails, creating calendar events, or managing resources in external services. + tags: + - Connected Accounts + summary: Execute a tool using a connected account + operationId: ToolService_ExecuteTool + responses: + '200': + description: Tool executed successfully with result data and execution ID + content: + application/json: + schema: + $ref: '#/components/schemas/toolsExecuteToolResponse' + '400': + description: Invalid request - occurs when tool name is missing, parameters are malformed, or tool definition validation fails + content: + application/json: + schema: {} + '401': + description: Authentication required - missing or invalid access token + content: + application/json: + schema: {} + '404': + description: Tool or connected account not found - occurs when the specified tool name or connected account does not exist + content: + application/json: + schema: {} + '500': + description: Tool execution failed - occurs when the external service returns an error or the tool encounters a runtime exception + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/toolsExecuteToolRequest' + required: true +webhooks: + connected_account.created: + post: + summary: Connected Account Created + description: Triggered when a new connected account is created + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_101531404017336586 + type: connected_account.created + object: ConnectedAccount + occurred_at: '2025-12-01T10:23:52.702980847Z' + environment_id: env_88640229614813449 + data: + authorization_type: OAUTH + connection_id: conn_100668583155073286 + id: ca_101531404000559370 + identifier: Bruce + provider: CANVA + status: PENDING_AUTH + responses: + '200': + description: Webhook received successfully + connected_account.updated: + post: + summary: Connected Account Updated + description: Triggered when a connected account is updated + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_101652975398683158 + type: connected_account.updated + object: ConnectedAccount + occurred_at: '2025-12-02T06:31:34.895815554Z' + environment_id: env_88640229614813449 + display_name: Connected account updated + data: + authorization_type: OAUTH + connection_id: conn_100510054016352776 + id: ca_100510623602835982 + identifier: Pranesh + provider: SUPABASE + status: PENDING_AUTH + responses: + '200': + description: Webhook received successfully + connected_account.deleted: + post: + summary: Connected Account Deleted + description: Triggered when a connected account is deleted + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_101653010731500290 + type: connected_account.deleted + object: ConnectedAccount + occurred_at: '2025-12-02T06:31:55.954027187Z' + environment_id: env_88640229614813449 + display_name: connected account deleted + data: + authorization_type: OAUTH + connection_id: conn_101644109747323155 + id: ca_101649788113519113 + identifier: Clark + last_used_at: '2025-12-02T06:00:01.374253Z' + provider: GOOGLE_ADS + status: ACTIVE + token_expires_at: '2025-12-02T06:59:57.237447Z' + responses: + '200': + description: Webhook received successfully + connected_account.magic_link_generated: + post: + summary: Connected Account Magic Link Generated + description: Triggered when a magic link is generated for OAuth flow + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_101652975398683158 + type: connected_account.magic_link_generated + object: ConnectedAccount + occurred_at: '2025-12-02T06:31:34.895815554Z' + environment_id: env_88640229614813448 + data: + authorization_type: OAUTH + connection_id: conn_100510054016352776 + id: ca_100510623602835982 + identifier: Pranesh + provider: SUPABASE + status: PENDING_AUTH + responses: + '200': + description: Webhook received successfully + connected_account.oauth_tokens_fetched: + post: + summary: Connected Account OAuth Tokens Fetched + description: Triggered when OAuth tokens are successfully fetched + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_101649795042509316 + type: connected_account.oauth_tokens_fetched + object: ConnectedAccount + occurred_at: '2025-12-02T05:59:59.250126407Z' + environment_id: env_88640229614813449 + data: + authorization_type: OAUTH + connection_id: conn_101644109747323155 + id: ca_101649788113519113 + identifier: Clark + provider: GOOGLE_ADS + status: ACTIVE + token_expires_at: '2025-12-02T06:59:57.237447778Z' + responses: + '200': + description: Webhook received successfully + connected_account.token_refresh_succeeded: + post: + summary: Connected Account Token Refresh Succeeded + description: Triggered when token refresh succeeds + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_101651946317808143 + type: connected_account.token_refresh_succeeded + object: ConnectedAccount + occurred_at: '2025-12-02T06:21:21.517480021Z' + environment_id: env_88640229614813449 + data: + authorization_type: OAUTH + connection_id: conn_101644109747323155 + id: ca_101644170698948883 + identifier: Pranesh + last_used_at: '2025-12-02T06:21:21.393723232Z' + provider: GOOGLE_ADS + status: ACTIVE + token_expires_at: '2025-12-02T07:21:20.508197312Z' + responses: + '200': + description: Webhook received successfully + connected_account.token_refresh_failed: + post: + summary: Connected Account Token Refresh Failed + description: Triggered when token refresh fails + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_101649795042509316 + type: connected_account.token_refresh_failed + object: ConnectedAccount + occurred_at: '2025-12-02T05:59:59.250126407Z' + environment_id: env_88640229614813445 + data: + authorization_type: OAUTH + connection_id: conn_101644109747323155 + id: ca_101649788113519113 + identifier: Clark + provider: GOOGLE_ADS + status: ACTIVE + token_expires_at: '2025-12-02T06:59:57.237447778Z' + responses: + '200': + description: Webhook received successfully + connected_account.oauth_succeeded: + post: + summary: Connected Account OAuth Succeeded + description: Triggered when OAuth authentication succeeds + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_101649484227871236 + type: connected_account.oauth_succeeded + object: ConnectedAccount + occurred_at: '2025-12-02T05:56:53.994604757Z' + environment_id: env_88640229614813449 + data: + authorization_type: OAUTH + connection_id: conn_101644109747323155 + id: ca_101649474950005257 + identifier: Bruce + provider: GOOGLE_ADS + status: ACTIVE + token_expires_at: '2025-12-02T06:56:52.976081699Z' + responses: + '200': + description: Webhook received successfully +components: + securitySchemes: + oauth2: + type: oauth2 + flows: + clientCredentials: + tokenUrl: https://$SCALEKIT_ENVIRONMENT_URL/oauth/token + scopes: + '': No scope required for client credentials flow + schemas: + connected_accountsConnectorType: + description: |- + - OAUTH: OAuth 2.0 authorization with access and refresh tokens + - API_KEY: Static API key authentication + - BASIC_AUTH: HTTP Basic Authentication (username/password) + - BEARER_TOKEN: Bearer token authentication + - CUSTOM: Custom authentication mechanism + - BASIC: Basic authentication (alias) + - OAUTH_M2M: OAuth 2.0 client credentials (machine-to-machine) + - TRELLO_OAUTH1: Trello token-based OAuth1-style browser authorization + - GOOGLE_DWD: Google Domain-Wide Delegation + type: string + title: Type of authentication mechanism used for the connected account + enum: + - OAUTH + - API_KEY + - BASIC_AUTH + - BEARER_TOKEN + - CUSTOM + - BASIC + - OAUTH_M2M + - TRELLO_OAUTH1 + - GOOGLE_DWD + connected_accountsConnectorStatus: + description: |- + - ACTIVE: Account is connected and credentials are valid + - EXPIRED: Access token has expired and needs refresh + - PENDING_AUTH: Account awaiting user authorization (re-auth initiated) + - PENDING_VERIFICATION: OAuth complete; awaiting user identity verification + before activation + - DISCONNECTED: Account has been manually disconnected + type: string + title: Status of a connected account indicating its current state + enum: + - ACTIVE + - EXPIRED + - PENDING_AUTH + - PENDING_VERIFICATION + - DISCONNECTED + connected_accountsConnectedAccountForList: + type: object + title: Connected account summary for list operations - excludes sensitive authorization details + properties: + authorization_type: + description: Authorization mechanism type. + $ref: '#/components/schemas/connected_accountsConnectorType' + connection_id: + description: Parent connection configuration reference. + type: string + examples: + - conn_24834495392086178 + connector: + description: Connector identifier. + type: string + examples: + - notion + id: + description: Unique connected account identifier. + type: string + examples: + - ca_24834495392086178 + identifier: + description: The unique identifier for this account in the third-party service. + type: string + examples: + - user@example.com + last_used_at: + description: Last usage timestamp. + type: string + format: date-time + examples: + - '2024-03-20T14:30:00Z' + provider: + description: OAuth provider name (e.g., 'google', 'microsoft'). + type: string + examples: + - google + status: + description: Current connection status. + $ref: '#/components/schemas/connected_accountsConnectorStatus' + token_expires_at: + description: Token expiration timestamp. + type: string + format: date-time + examples: + - '2024-12-31T23:59:59Z' + updated_at: + description: Last modification timestamp. + type: string + format: date-time + examples: + - '2024-03-20T15:04:05Z' + connected_accountsListConnectedAccountsResponse: + type: object + properties: + connected_accounts: + description: List of connected accounts matching the filter criteria. Excludes sensitive authorization details for security. + type: array + items: + type: object + $ref: '#/components/schemas/connected_accountsConnectedAccountForList' + next_page_token: + description: Pagination token for retrieving the next page. Empty if this is the last page. Pass this value to page_token in the next request. + type: string + examples: + - eyJvZmZzZXQiOjIwfQ== + prev_page_token: + description: Pagination token for retrieving the previous page. Empty if this is the first page. Pass this value to page_token to go back. + type: string + examples: + - eyJvZmZzZXQiOjB9 + total_size: + description: Total count of connected accounts matching the filter criteria across all pages. Use for calculating pagination. + type: integer + format: int64 + examples: + - 100 + connected_accountsGoogleDWDAuth: + description: |- + Google Domain-Wide Delegation authentication — used for GOOGLE_DWD connections. + Send only subject in requests; access_token, scopes, and token_expires_at are response-only. + type: object + properties: + access_token: + description: OAuth access token acquired via the jwt-bearer grant. Present in responses only. + type: string + readOnly: true + examples: + - ya29.a0AfH6SMBx... + scopes: + description: OAuth scopes granted to this token. Present in responses only. + type: array + items: + type: string + readOnly: true + examples: + - - openid + - https://www.googleapis.com/auth/userinfo.email + subject: + description: Email address of the Google Workspace user to impersonate via Domain-Wide Delegation. + type: string + examples: + - user@example.com + token_expires_at: + description: When the access token expires. Present in responses only. + type: string + format: date-time + readOnly: true + connected_accountsOauthToken: + type: object + title: OAuth 2.0 access and refresh tokens with scopes + properties: + access_token: + description: OAuth access token for API requests. Typically short-lived and must be refreshed after expiration. + type: string + examples: + - ya29.a0AfH6SMBx... + domain: + description: Associated domain for workspace or organization-scoped OAuth connections (e.g., Google Workspace domain). + type: string + examples: + - example.com + refresh_token: + description: OAuth refresh token for obtaining new access tokens. Long-lived and used to maintain persistent authorization. + type: string + examples: + - 1//0gHJxZ-Lb2... + scopes: + description: List of granted OAuth scopes defining the permissions and access levels for this connection. + type: array + items: + type: string + examples: + - - https://www.googleapis.com/auth/drive.readonly + - https://www.googleapis.com/auth/userinfo.email + connected_accountsStaticAuth: + type: object + title: Static authentication credentials for API keys, bearer tokens, or basic auth + properties: + details: + description: Flexible JSON structure containing static credentials. Format varies by connector type (API key, username/password, etc.). + type: object + examples: + - api_key: sk_live_... + api_secret: ... + connected_accountsAuthorizationDetails: + type: object + title: Authentication credentials container supporting multiple auth types + properties: + google_dwd: + title: Google Domain-Wide Delegation credentials + $ref: '#/components/schemas/connected_accountsGoogleDWDAuth' + oauth_token: + title: OAuth 2.0 credentials + $ref: '#/components/schemas/connected_accountsOauthToken' + static_auth: + title: Static authentication credentials + $ref: '#/components/schemas/connected_accountsStaticAuth' + v1connected_accountsUpdateConnectedAccount: + type: object + title: Payload for updating an existing connected account - all fields optional + properties: + api_config: + description: Updated JSON configuration for API-specific settings. Merges with existing configuration - only provided fields are modified. + type: object + examples: + - rate_limit: 2000 + timeout: 60 + authorization_details: + description: Updated authentication credentials. Provide new OAuth tokens (e.g., after refresh) or updated static auth details. Only included fields will be modified. + $ref: '#/components/schemas/connected_accountsAuthorizationDetails' + examples: + - oauth_token: + access_token: ya29.new_token... + refresh_token: 1//0g... + scopes: + - email + - profile + - calendar + connected_accountsUpdateConnectedAccountRequest: + type: object + properties: + connected_account: + description: Details of the connected account to update + $ref: '#/components/schemas/v1connected_accountsUpdateConnectedAccount' + examples: + - authorization_details: + oauth_token: + access_token: ... + refresh_token: ... + scopes: + - read + - write + authorization_type: OAUTH2 + connector: + description: Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed. + type: string + examples: + - notion + id: + description: Unique identifier for the connected account to update + type: string + examples: + - ca_123 + identifier: + description: The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier). + type: string + examples: + - user@example.com + organization_id: + description: Organization ID for the connector + type: string + examples: + - org_121312434123312 + user_id: + description: User ID for the connector + type: string + examples: + - user_121312434123312 + connected_accountsConnectedAccount: + type: object + properties: + api_config: + description: Optional JSON configuration for connector-specific API settings such as rate limits, custom endpoints, or feature flags. + type: object + examples: + - base_url: https://api.custom-domain.com + rate_limit: 1000 + timeout: 30 + authorization_details: + description: Sensitive authentication credentials including access tokens, refresh tokens, and scopes. Contains either OAuth tokens or static auth details. + $ref: '#/components/schemas/connected_accountsAuthorizationDetails' + authorization_type: + description: Type of authorization mechanism used. Specifies whether this connection uses OAuth, API keys, bearer tokens, or other auth methods. + $ref: '#/components/schemas/connected_accountsConnectorType' + connection_id: + description: Reference to the parent connection configuration. Links this account to a specific connector setup in your environment. + type: string + examples: + - conn_24834495392086178 + connector: + description: Connector identifier (e.g., 'notion', 'slack', 'salesforce'). Indicates which third-party application this account connects to. + type: string + examples: + - notion + id: + description: Unique Scalekit-generated identifier for this connected account. Always prefixed with 'ca_'. + type: string + examples: + - ca_24834495392086178 + identifier: + description: The unique identifier for this account in the third-party service. Typically an email address, user ID, or workspace identifier. + type: string + examples: + - user@example.com + last_used_at: + description: Timestamp when this connected account was last used to make an API call. Useful for tracking active connections. + type: string + format: date-time + examples: + - '2024-03-20T14:30:00Z' + provider: + description: OAuth provider name (e.g., 'google', 'microsoft', 'github'). Identifies which authentication service manages this connection. + type: string + examples: + - google + status: + description: Current status of the connected account. Indicates if the account is active, expired, pending authorization, or pending user identity verification. + $ref: '#/components/schemas/connected_accountsConnectorStatus' + token_expires_at: + description: Expiration timestamp for the access token. After this time, the token must be refreshed or re-authorized. + type: string + format: date-time + examples: + - '2024-12-31T23:59:59Z' + updated_at: + description: Timestamp when this connected account was last modified. Updated whenever credentials or configuration changes. + type: string + format: date-time + examples: + - '2024-03-20T15:04:05Z' + connected_accountsUpdateConnectedAccountResponse: + type: object + properties: + connected_account: + description: The updated connected account with refreshed credentials, new token expiry, and modified configuration settings. + $ref: '#/components/schemas/connected_accountsConnectedAccount' + v1connected_accountsCreateConnectedAccount: + type: object + title: Payload for creating a new connected account - authorization details are optional + properties: + api_config: + description: Optional JSON configuration for connector-specific API settings such as rate limits, custom API endpoints, timeouts, or feature flags. + type: object + examples: + - base_url: https://api.custom-domain.com + rate_limit: 1000 + timeout: 30 + authorization_details: + description: Optional authentication credentials for the connected account. Include OAuth tokens (access_token, refresh_token, scopes) or static auth details (API keys, bearer tokens). Can be provided later via update. + $ref: '#/components/schemas/connected_accountsAuthorizationDetails' + examples: + - oauth_token: + access_token: ya29.a0... + refresh_token: 1//0g... + scopes: + - email + - profile + connected_accountsCreateConnectedAccountRequest: + type: object + properties: + connected_account: + description: Details of the connected account to create + $ref: '#/components/schemas/v1connected_accountsCreateConnectedAccount' + examples: + - authorization_details: + oauth_token: + access_token: ... + refresh_token: ... + scopes: + - read + - write + authorization_type: OAUTH2 + connector: + description: Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed. + type: string + examples: + - notion + identifier: + description: The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier). + type: string + examples: + - user@example.com + organization_id: + description: Organization ID for the connector + type: string + examples: + - org_121312434123312 + user_id: + description: User ID for the connector + type: string + examples: + - user_121312434123312 + connected_accountsCreateConnectedAccountResponse: + type: object + properties: + connected_account: + description: The newly created connected account with its unique identifier, status, and complete authorization details including access tokens. + $ref: '#/components/schemas/connected_accountsConnectedAccount' + connected_accountsGetConnectedAccountByIdentifierResponse: + type: object + properties: + connected_account: + description: The connected account with complete details including sensitive authorization credentials (access tokens, refresh tokens, scopes). Handle with appropriate access controls. + $ref: '#/components/schemas/connected_accountsConnectedAccount' + connected_accountsGetMagicLinkForConnectedAccountRequest: + type: object + properties: + connector: + description: Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed. + type: string + examples: + - notion + id: + description: Unique identifier for the connected account + type: string + examples: + - ca_123 + identifier: + description: The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier). + type: string + examples: + - user@example.com + organization_id: + description: Organization ID for the connector + type: string + examples: + - org_121312434123312 + state: + description: Optional opaque state value. State added to the user verify redirect URL query params to validate the user verification + type: string + examples: + - QVNDSUFyY2hhYml0dGVyXzE2ODQ5NzIwNzI0NTY= + user_id: + description: User ID for the connector + type: string + examples: + - user_121312434123312 + user_verify_url: + description: B2B app's user verify redirect URL + type: string + examples: + - https://app.yourapp.com/user/verify/callback + connected_accountsGetMagicLinkForConnectedAccountResponse: + type: object + properties: + expiry: + description: Expiry timestamp for the authentication link + type: string + format: date-time + examples: + - '2024-03-20T15:04:05Z' + link: + description: Authentication link for the connector + type: string + examples: + - https://notion.com/oauth/authorize?client_id=... + connected_accountsVerifyConnectedAccountUserRequest: + type: object + required: + - auth_request_id + - identifier + properties: + auth_request_id: + description: Auth request ID as base64url-encoded opaque token from the user verify redirect URL query params + type: string + examples: + - QVNDSUFyY2hhYml0dGVyXzE2ODQ5NzIwNzI0NTY= + identifier: + description: Current logged in user's connected account identifier + type: string + examples: + - user@example.com + connected_accountsVerifyConnectedAccountUserResponse: + type: object + properties: + post_user_verify_redirect_url: + description: URL to redirect the user to after successful verification + type: string + examples: + - https://env1.example.com/connect/success + connected_accountsDeleteConnectedAccountRequest: + type: object + properties: + connector: + description: Connector identifier (e.g., 'notion', 'slack', 'google'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed. + type: string + examples: + - notion + id: + description: Unique identifier for the connected account to delete + type: string + examples: + - ca_123 + identifier: + description: The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier). + type: string + examples: + - user@example.com + organization_id: + description: Organization ID for the connector + type: string + examples: + - org_121312434123312 + user_id: + description: User ID for the connector + type: string + examples: + - user_121312434123312 + connected_accountsSearchConnectedAccountsResponse: + type: object + properties: + connected_accounts: + description: List of connected accounts matching the search query. Excludes sensitive authorization details. + type: array + items: + type: object + $ref: '#/components/schemas/connected_accountsConnectedAccountForList' + next_page_token: + description: Pagination token for the next page. Empty if this is the last page. + type: string + examples: + - eyJvZmZzZXQiOjMwfQ== + prev_page_token: + description: Pagination token for the previous page. Empty if this is the first page. + type: string + examples: + - eyJvZmZzZXQiOjB9 + total_size: + description: Total count of accounts matching the search query across all pages. + type: integer + format: int64 + examples: + - 100 + toolsExecuteToolRequest: + type: object + properties: + agent_run_id: + description: Optional. Customer-supplied identifier grouping multiple tool calls into a single agent run. Useful for correlating logs across an agentic workflow. + type: string + examples: + - run_abc123 + connected_account_id: + description: Optional. The unique ID of the connected account. Use this to directly identify the connected account instead of using identifier + connector combination. + type: string + examples: + - ca_123 + connector: + description: Optional. The name of the connector/provider (e.g., 'Google Workspace', 'Slack', 'Notion'). Alphanumeric characters, spaces, hyphens, underscores, and colons are allowed. Use this in combination with identifier to identify the connected account. + type: string + examples: + - Google Workspace + identifier: + description: Optional. The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier). Use this in combination with connector to identify the connected account. + type: string + examples: + - user@example.com + organization_id: + description: Optional. The organization ID to scope the connected account lookup. Use this to narrow down the search when the same identifier exists across multiple organizations. + type: string + examples: + - org_123 + params: + description: JSON object containing the parameters required for tool execution. The structure depends on the specific tool being executed. + type: object + examples: + - body: Hello World + subject: Hello + to: user@example.com + tool_name: + description: Name of the tool to execute + type: string + examples: + - send_email + user_id: + description: Optional. The user ID to scope the connected account lookup. Use this to narrow down the search when the same identifier exists across multiple users. + type: string + examples: + - user_123 + toolsExecuteToolResponse: + type: object + properties: + data: + description: Free-flowing JSON parameters for the tool execution + type: object + examples: + - body: Hello World + subject: Hello + to: user@example.com + execution_id: + description: Unique identifier for the tool execution + type: string + examples: + - '123456789' + ScalekitEvent: + type: object + required: + - spec_version + - id + - type + - occurred_at + - environment_id + - object + properties: + spec_version: + type: string + example: '1' + description: The webhook specification version + pattern: ^[0-9]+$ + id: + type: string + pattern: ^evt_ + example: evt_1234567890abcdef + description: Unique identifier for the webhook event (must be prefixed with "evt_") + minLength: 1 + maxLength: 32 + type: + type: string + example: organization.created + description: The event type + enum: + - organization.created + - organization.updated + - organization.deleted + - organization.sso_created + - organization.sso_deleted + - organization.sso_enabled + - organization.sso_disabled + - user.signup + - user.login + - user.logout + - user.organization_invitation + - user.organization_membership_created + - user.organization_membership_updated + - user.organization_membership_deleted + - organization.directory.user_created + - organization.directory.user_updated + - organization.directory.user_deleted + - organization.directory.group_created + - organization.directory.group_updated + - organization.directory.group_deleted + - organization.directory_enabled + - organization.directory_disabled + - role.created + - role.updated + - role.deleted + - permission.created + - permission.updated + - permission.deleted + occurred_at: + type: string + format: date-time + description: When the event occurred (ISO 8601 format) + example: '2024-01-01T00:00:00Z' + environment_id: + type: string + pattern: ^env_ + example: env_1234567890abcdef + description: The environment ID where the event occurred + minLength: 1 + maxLength: 32 + organization_id: + type: string + pattern: ^org_ + example: org_1234567890abcdef + description: The organization ID (if applicable) + minLength: 1 + maxLength: 32 + object: + type: string + description: The type of object that triggered the webhook + enum: + - Organization + - Connection + - Role + - Directory + - DirectoryUser + - DirectoryGroup + - Permission + - OrgMembership + - User + example: Organization + data: + type: object + description: The event payload (structure varies by event type) + additionalProperties: true + example: + id: org_1234567890abcdef + name: Example Organization + created_at: '2024-01-01T00:00:00Z' + display_name: + type: string + description: Human-readable display name for the event + example: Organization Created + minLength: 1 + maxLength: 200 diff --git a/public/api/saaskit.scalar.yaml b/public/api/saaskit.scalar.yaml new file mode 100644 index 000000000..41e7b49c8 --- /dev/null +++ b/public/api/saaskit.scalar.yaml @@ -0,0 +1,9584 @@ +openapi: 3.1.1 +info: + description: "# Overview\n\nThe Scalekit API is a RESTful API that enables you to manage organizations, users, and authentication settings. All requests must use HTTPS.\nAll API requests use the following base URLs:\n\n```\nhttps://{your-subdomain}.scalekit.dev (Development)\nhttps://{your-subdomain}.scalekit.com (Production)\nhttps://auth.yourapp.com (Custom domain)\n```\n\nScalekit operates two separate environments: Development and Production. Resources cannot be moved between environments.\n\n## Quickstart\n\nThe Scalekit API uses OAuth 2.0 Client Credentials for authentication.\n\nCopy your API credentials from the Scalekit dashboard's API Config section and set them as environment variables.\n\n```sh\nSCALEKIT_ENVIRONMENT_URL=''\nSCALEKIT_CLIENT_ID=''\nSCALEKIT_CLIENT_SECRET=''\n```\n\nGetting an access token\n\n1. Get your credentials from the [Scalekit Dashboard](https://app.scalekit.com)\n2. Request an access token:\n\n```sh\ncurl https:///oauth/token \\\n -X POST \\\n -H 'Content-Type: application/x-www-form-urlencoded' \\\n -d 'client_id={client_id}' \\\n -d 'client_secret={client_secret}' \\\n -d 'grant_type=client_credentials'\n```\n\n3. Use the access token in API requests:\n\n```sh\ncurl https:///api/v1/organizations \\\n -H 'Content-Type: application/json' \\\n -H 'Authorization: Bearer {access_token}'\n```\n\nThe response includes an access token:\n\n```json\n{\n\t\"access_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6InNua181Ok4OTEyMjU2NiIsInR5cCI6IkpXVCJ9...\",\n\t\"token_type\": \"Bearer\",\n\t\"expires_in\": 86399,\n\t\"scope\": \"openid\"\n}\n```\n\n## SDKs\n\nScalekit provides official SDKs for multiple programming languages. Check the changelog at GitHub repositories for the latest updates.\n\n### Node.js\n\n```sh\nnpm install @scalekit-sdk/node\n```\n\nCreate a new Scalekit client instance after initializing the environment variables\n\n```js\nimport { Scalekit } from \"@scalekit-sdk/node\";\n\nexport let scalekit = new Scalekit(\n\tprocess.env.SCALEKIT_ENVIRONMENT_URL,\n\tprocess.env.SCALEKIT_CLIENT_ID,\n\tprocess.env.SCALEKIT_CLIENT_SECRET\n);\n```\n\n[See the Node SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-node/releases)\n\n### Python\n\n```sh\npip install scalekit-sdk-python\n```\n\nCreate a new Scalekit client instance after initializing the environment variables.\n\n```py\nfrom scalekit import ScalekitClient\nimport os\n\nscalekit_client = ScalekitClient(\n os.environ.get('SCALEKIT_ENVIRONMENT_URL'),\n os.environ.get('SCALEKIT_CLIENT_ID'),\n os.environ.get('SCALEKIT_CLIENT_SECRET')\n)\n```\n\n[See the Python SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-python/releases)\n\n### Go\n\n```sh\ngo get -u github.com/scalekit-inc/scalekit-sdk-go\n```\n\nCreate a new Scalekit client instance after initializing the environment variables.\n\n```go\npackage main\n\nimport (\n \"os\"\n \"github.com/scalekit-inc/scalekit-sdk-go\"\n)\n\nscalekitClient := scalekit.NewScalekitClient(\n os.Getenv(\"SCALEKIT_ENVIRONMENT_URL\"),\n os.Getenv(\"SCALEKIT_CLIENT_ID\"),\n os.Getenv(\"SCALEKIT_CLIENT_SECRET\"),\n)\n```\n\n[See the Go SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-go/releases)\n\n### Java\n\n```gradle\n/* Gradle users - add the following to your dependencies in build file */\nimplementation \"com.scalekit:scalekit-sdk-java:2.0.11\"\n```\n\n```xml\n\n\n com.scalekit\n scalekit-sdk-java\n 2.0.11\n\n```\n\n[See the Java SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-java/releases)\n\n### Error handling\n\nThe API uses standard HTTP status codes:\n\n| Code | Description |\n| ----------- | -------------------- |\n| 200/201 | Success |\n| 400 | Invalid request |\n| 401 | Authentication error |\n| 404 | Resource not found |\n| 429 | Rate limit exceeded |\n| 500/501/504 | Server error |\n\nError responses include detailed information:\n\n```json\n{\n\t\"code\": 16,\n\t\"message\": \"Token empty\",\n\t\"details\": [\n\t\t{\n\t\t\t\"@type\": \"type.googleapis.com/scalekit.v1.errdetails.ErrorInfo\",\n\t\t\t\"error_code\": \"UNAUTHENTICATED\"\n\t\t}\n\t]\n}\n```\n" + title: Scalekit APIs + contact: + name: Scalekit Inc + url: https://scalekit.com + email: support@scalekit.com + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0 + version: 1.0.0 + x-scalar-sdk-installation: + - lang: shell + description: Set up OAuth 2.0 Client Credentials authentication to access Scalekit APIs. Includes credential configuration, token exchange, and authenticated API request examples. + source: | + + # 1. Obtain API Credentials + # Get your credentials from the Scalekit dashboard + export SCALEKIT_ENVIRONMENT_URL="https://your-org.scalekit.dev" # Your Scalekit environment URL + export SCALEKIT_CLIENT_ID="your_client_id" # Your client ID + export SCALEKIT_CLIENT_SECRET="your_client_secret" # Your client secret + + # 2. Exchange client credentials an OAuth 2.0 access token + TOKEN_RESPONSE=$(curl -s -X POST "${SCALEKIT_ENVIRONMENT_URL}/oauth/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "client_id=${SCALEKIT_CLIENT_ID}" \ + -d "client_secret=${SCALEKIT_CLIENT_SECRET}" \ + -d "grant_type=client_credentials") + + # 3. Make Authenticated API Requests + curl -X GET "${SCALEKIT_ENVIRONMENT_URL}/api/v1/organizations" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${ACCESS_TOKEN}" \ + -H "Accept: application/json" +servers: + - url: https://$SCALEKIT_ENVIRONMENT_URL +security: + - oauth2: [] +tags: + - description: | + Organization represents a customer or a tenant of your product. This is the top level entity and all resources are mapped to this Organization object. Each organization is uniquely identified by `organization_id`. + + + name: Organizations + - description: Permission management for defining and controlling access to system resources. Create, retrieve, update, and delete granular permissions that represent specific actions users can perform. Permissions are the building blocks of role-based access control (RBAC) and can be assigned to roles to grant users the ability to perform specific operations. Use this service to define custom permissions for your application's unique access control requirements. + name: Permissions + - description: Comprehensive user management operations including user lifecycle, organization memberships, and invitation workflows. This service provides endpoints for creating, retrieving, updating, and deleting user accounts across your Scalekit environment. It supports both individual user operations and bulk operations for user administration, including user search, pagination, and metadata management. The service also handles user invitations and organization membership management. + name: Users + - description: Manage enterprise connections for your Scalekit environment. This service provides endpoints for retrieving, and updating connections. + name: Connections + - description: Directory management for viewing and controlling external identity provider connections in your Scalekit environment. This service provides endpoints for retrieving directory information, listing directories and their contents, and enabling or disabling directory synchronization. + name: Directory + - description: Role-based access control (RBAC) for defining and managing permissions in an environment. Create and update custom roles with explicit permissions, model role hierarchies through inheritance, view dependent roles, manage role-permission assignments, and list roles and permissions. Also provides a utility to count users assigned to a role. + name: Roles + - description: Comprehensive session management for user authentication and authorization. This service provides endpoints for retrieving session details, managing user sessions across devices, revoking individual sessions, and terminating all active sessions for a user. It supports session auditing, device tracking, and security monitoring with detailed session metadata including device information, IP geolocation, and activity timestamps. + name: Sessions + - description: | + Manage organization-level domains. Scalekit supports two domain types: + + - ORGANIZATION_DOMAIN: Used for SSO domain discovery. When a user signs in with a matching email domain, Scalekit routes them to the organization’s SSO provider and enforces SSO. + - ALLOWED_EMAIL_DOMAIN: Used to mark trusted email domains for an organization. When a user signs in or signs up with a matching domain, Scalekit suggests the organization in the organization switcher (authentication-method agnostic). + name: Domains + - description: Endpoints for managing API client applications. API clients enable secure, automated interactions between software systems without human intervention. Each client is uniquely identified by a `client_id` and can be configured with authentication settings, redirect URIs, and security parameters. Use these endpoints to create, manage, and configure API clients for your API clients. + name: API Auth + externalDocs: + url: https://docs.scalekit.com/m2m/overview + - description: Endpoints for sending and verifying passwordless authentication emails. These APIs allow users to authenticate without passwords by receiving a verification code or magic link in their email. + name: Magic link & OTP + - description: Endpoints for passkey-based authentication using WebAuthn/FIDO2 standards. + name: Passkeys +externalDocs: + description: Scalekit Docs + url: https://docs.scalekit.com/ +paths: + /api/v1/connections: + get: + description: Retrieves a list of connections in the environment + tags: + - Connections + summary: List connections + operationId: ConnectionService_ListConnections + parameters: + - schema: + type: string + description: Filter connections by organization identifier + name: organization_id + in: query + - schema: + type: string + description: Filter connections by email domain associated with the organization + name: domain + in: query + - schema: + type: string + description: Filter connections by status. Use 'all' to include all connections regardless of status. Default behavior shows only active (completed and enabled) connections + name: include + in: query + responses: + '200': + description: Successfully retrieved connections + content: + application/json: + schema: + $ref: '#/components/schemas/connectionsListConnectionsResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + // List connections by organization id + const connections = await scalekit.connection.listConnections(organizationId); + + // List connections by domain + const connections = await scalekit.connection.listConnectionsByDomain(domain); + - label: Python SDK + lang: python + source: |- + # List connections by organization id + connections = scalekit_client.connection.list_connections( + organization_id + ) + + # List connections by domain + response = scalekit_client.connection.list_connections_by_domain(domain="example.com") + - label: Go SDK + lang: go + source: |- + // List connections by organization id + connections, err := scalekitClient.Connection().ListConnections( + ctx, + organizationId + ) + + // List connections by domain + connections, err := scalekitClient.Connection().ListConnectionsByDomain(ctx, + domain) + - label: Java SDK + lang: java + source: |- + // List connections by organization id + ListConnectionsResponse response = scalekitClient.connections( + ).listConnections(organizationId); + + // List connections by domain + ListConnectionsResponse response = scalekitClient.connections( + ).listConnectionsByDomain("your-domain.com"); + /api/v1/invites/organizations/{organization_id}/users/{id}/resend: + patch: + description: Resends an invitation email to a user who has a pending or expired invitation in the specified organization. If the invitation has expired, a new invitation will be automatically created and sent. If the invitation is still valid, a reminder email will be sent instead. Use this endpoint when a user hasn't responded to their initial invitation and you need to send them a reminder or when the original invitation has expired. The invitation email includes a secure magic link that allows the user to complete their account setup and join the organization. Each resend operation increments the resent counter. + tags: + - Users + summary: Resend user invitation email + operationId: UserService_ResendInvite + parameters: + - schema: + type: string + description: Unique identifier of the organization containing the pending invitation. Must start with 'org_' and be 1-32 characters long. + name: organization_id + in: path + required: true + - schema: + type: string + description: System-generated user ID of the user who has a pending invitation. Must start with 'usr_' and be 19-25 characters long. + name: id + in: path + required: true + responses: + '200': + description: Successfully resent the invitation email. Returns the updated invitation object with organization ID, user ID, membership status, timestamps, and resent count. If expired, a new invitation is created; otherwise, the existing one is resent. + content: + application/json: + schema: + $ref: '#/components/schemas/usersResendInviteResponse' + '400': + description: Invalid request — common causes include user ID or organization ID is invalid, full-stack authentication is disabled, user profile is missing, invite already accepted, or missing expiry time in user management settings. + content: + application/json: + schema: + $ref: '#/components/schemas/errdetailsErrorInfo' + '404': + description: Resource not found — the specified user, organization, membership, or invitation could not be found in the specified environment. Verify that all IDs are correct and that the resources exist before attempting to resend an invitation. + content: + application/json: + schema: + $ref: '#/components/schemas/errdetailsErrorInfo' + '500': + description: Internal server error — an unexpected error occurred while processing the invitation resend request. This may be due to database connectivity issues, problems generating the secure magic link, email delivery service failures, or transaction errors during invitation processing. Contact support if the problem persists. + content: + application/json: + schema: + $ref: '#/components/schemas/errdetailsErrorInfo' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserServiceResendInviteBody' + required: true + /api/v1/memberships/organizations/{organization_id}/users/{id}: + post: + description: Adds an existing user to an organization and assigns them specific roles and permissions. Use this endpoint when you want to grant an existing user access to a particular organization. You can specify roles, metadata, and other membership details during the invitation process. + tags: + - Users + summary: Add existing user to organization + operationId: UserService_CreateMembership + parameters: + - schema: + type: string + description: Unique identifier of the target organization. Must start with 'org_' and be 1-32 characters long. + name: organization_id + in: path + required: true + - schema: + type: string + description: System-generated user ID. Must start with 'usr_' (19-25 characters) + name: id + in: path + required: true + - schema: + type: string + description: External system identifier from connected directories. Must be unique across the system + name: external_id + in: query + - schema: + type: boolean + description: If true, sends an activation email to the user. Defaults to true. + name: send_invitation_email + in: query + responses: + '201': + description: User successfully added to the organization. Returns details of the updated membership details + content: + application/json: + schema: + $ref: '#/components/schemas/usersCreateMembershipResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: "import { ScalekitClient } from \"@scalekit-sdk/node\";\nconst scalekit = new ScalekitClient(\n\tprocess.env.SCALEKIT_ENV_URL,\n\tprocess.env.SCALEKIT_CLIENT_ID,\n\tprocess.env.SCALEKIT_CLIENT_SECRET\n);\nawait scalekit.user.createMembership(\"org_123\", \"usr_123\", {\n\troles: [\"admin\"],\n\tmetadata: {\n\t\tdepartment: \"engineering\",\n\t\tlocation: \"nyc-office\",\n\t},\n});" + - label: Python SDK + lang: python + source: |- + from scalekit.v1.users.users_pb2 import CreateMembership + from scalekit.v1.commons.commons_pb2 import Role + + membership = CreateMembership( + roles=[Role(name="admin")], + metadata={"department": "engineering", "location": "nyc-office"}, + ) + resp = scalekit_client.users.create_membership( + organization_id="org_123", + user_id="usr_123", + membership=membership, + ) + - label: Go SDK + lang: go + source: |- + func main() { + scalekitClient := scalekit.NewScalekitClient( + os.Getenv("SCALEKIT_ENV_URL"), + os.Getenv("SCALEKIT_CLIENT_ID"), + os.Getenv("SCALEKIT_CLIENT_SECRET"), + ) + membership := &usersv1.CreateMembership{ + Roles: []*usersv1.Role{{Name: "admin"}}, + Metadata: map[string]string{ + "department": "engineering", + "location": "nyc-office", + }, + } + resp, + err := scalekitClient.User().CreateMembership( + context.Background(), "org_123", + "usr_123", membership, false) + if err != nil { + panic(err) + } + } + - label: Java SDK + lang: java + source: |- + import com.scalekit.ScalekitClient; + import com.scalekit.api.UserClient; + import com.scalekit.grpc.scalekit.v1.users.*; + ScalekitClient scalekitClient = new ScalekitClient( + System.getenv("SCALEKIT_ENV_URL"), + System.getenv("SCALEKIT_CLIENT_ID"), + System.getenv("SCALEKIT_CLIENT_SECRET") + ); + UserClient users = scalekitClient.users(); + CreateMembershipRequest membershipReq = CreateMemb + ershipRequest.newBuilder() + .setMembership( + CreateMembership.newBuilder() + .addRoles(Role.newBuilder( + ).setName("admin").build()) + .putMetadata("department", "engineering") + .putMetadata("location", "nyc-office") + .build()) + .build(); + CreateMembershipResponse res = users. + createMembership("org_123", "usr_123", + membershipReq); + requestBody: + content: + application/json: + schema: + description: Membership details to create. Required fields must be provided. + required: + - membership + $ref: '#/components/schemas/v1usersCreateMembership' + required: true + delete: + description: Removes a user from an organization by user ID or external ID. If the user has no memberships left and cascade is true, the user is also deleted. This action is irreversible and may also remove related group memberships. + tags: + - Users + summary: Delete organization membership for user + operationId: UserService_DeleteMembership + parameters: + - schema: + type: string + description: Unique organization identifier. Must start with 'org_' and be 1-32 characters long + name: organization_id + in: path + required: true + - schema: + type: string + description: System-generated user ID. Must start with 'usr_' (19-25 characters) + name: id + in: path + required: true + - schema: + type: string + description: External system identifier from connected directories. Must match existing records + name: external_id + in: query + responses: + '200': + description: User successfully marked for deletion. No content returned + content: + application/json: + schema: {} + x-codeSamples: + - label: Python SDK + lang: python + source: |- + response = scalekit_client.users.delete_membership( + organization_id=org_id,user_id=user_id + ) + patch: + description: Updates a user's membership details within an organization by user ID or external ID. You can update roles and membership metadata. + tags: + - Users + summary: Update organization membership for user + operationId: UserService_UpdateMembership + parameters: + - schema: + type: string + description: Unique identifier of the organization containing the membership. Must start with 'org_' and be 1-32 characters long. + name: organization_id + in: path + required: true + - schema: + type: string + description: System-generated user ID. Must start with 'usr_' and be 19-25 characters long. + name: id + in: path + required: true + - schema: + type: string + description: Your application's unique identifier for this user. + name: external_id + in: query + responses: + '200': + description: Membership updated successfully. Returns the updated user object. + content: + application/json: + schema: + $ref: '#/components/schemas/usersUpdateMembershipResponse' + requestBody: + content: + application/json: + schema: + description: Membership fields to update. Only specified fields will be modified. + $ref: '#/components/schemas/v1usersUpdateMembership' + examples: + - role: admin + required: true + /api/v1/organizations: + get: + description: Retrieve a paginated list of organizations within your environment. The response includes a `page_token` that can be used to access subsequent pages of results. + tags: + - Organizations + summary: List organizations + operationId: OrganizationService_ListOrganization + parameters: + - schema: + type: integer + format: int64 + description: Maximum number of organizations to return per page. Must be between 10 and 100 + name: page_size + in: query + - schema: + type: string + description: Pagination token from the previous response. Use to retrieve the next page of organizations + name: page_token + in: query + - schema: + type: string + description: Your application's unique identifier for this organization, used to link Scalekit with your system + name: external_id + in: query + responses: + '200': + description: Successfully retrieved the list of organizations + content: + application/json: + schema: + $ref: '#/components/schemas/organizationsListOrganizationsResponse' + '400': + description: Invalid page token + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: "const organizations = await scalekit.organization.listOrganization({\n\tpageSize: 10,\n});" + - label: Python SDK + lang: python + source: |- + options = ListOrganizationOptions() + options.page_size = 10 + + organizations = scalekit_client.organization.list_organizations( + options=options + ) + - label: Go SDK + lang: go + source: |- + organizations, err := scalekitClient.Organization.ListOrganizations( + ctx, + &scalekit.ListOrganizationOptions{ + PageSize: 10, + } + ) + - label: Java SDK + lang: java + source: ListOrganizationsResponse organizations = scalekitClient.organizations().listOrganizations(10, ""); + post: + description: Creates a new organization in your environment. Use this endpoint to add a new tenant that can be configured with various settings and metadata + tags: + - Organizations + summary: Create an organization + operationId: OrganizationService_CreateOrganization + responses: + '201': + description: Returns the newly created organization with its unique identifier and settings + content: + application/json: + schema: + $ref: '#/components/schemas/organizationsCreateOrganizationResponse' + x-badges: + - name: '' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: "const organization = await scalekit.organization.createOrganization(name, {\n\n\texternalId: \"externalId\",\n\n});" + - label: Python SDK + lang: python + source: |- + options = CreateOrganizationOptions() + options.external_id = "externalId" + organization = scalekit_client.organization.create_organization( + name, + options=options + ) + - label: Go SDK + lang: go + source: |- + organization, err := ScalekitClient.Organization.CreateOrganization( + ctx, + name, + scalekit.CreateOrganizationOptions{ + ExternalID: "externalId", + }, + ) + - label: Java SDK + lang: java + source: |- + CreateOrganization createOrganization = CreateOrganization.newBuilder() + .setDisplayName("Test Org") + .build(); + + Organization createdOrganization = scalekitClient.organizations().create(createOrganization); + requestBody: + content: + application/json: + schema: + description: Required parameters for creating a new organization + $ref: '#/components/schemas/v1organizationsCreateOrganization' + description: Organization details + required: true + /api/v1/organizations/{id}: + get: + description: Retrieves organization details by Scalekit ID, including name, region, metadata, and settings + tags: + - Organizations + summary: Get organization details + operationId: OrganizationService_GetOrganization + parameters: + - schema: + type: string + description: Unique Scalekit-generated identifier for an organization. Use this with the GetOrganization endpoint. Do not pass this parameter when calling GetOrganizationByExternalId — use external_id instead. + name: id + in: path + required: true + responses: + '200': + description: Returns the complete organization object with ID, display name, settings, and metadata + content: + application/json: + schema: + $ref: '#/components/schemas/organizationsGetOrganizationResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + const scalekit = new ScalekitClient( + , + , + + ); + + const organization = await scalekit.organization.getOrganization(organization_id); + - label: Python SDK + lang: python + source: |- + scalekit_client = ScalekitClient( + , + , + + ) + + organization = scalekit_client.organization.get_organization( + organization_id + ) + - label: Go SDK + lang: go + source: |- + scalekitClient := scalekit.NewScalekitClient( + , + , + + ) + + organization, err := scalekitClient.Organization.GetOrganization( + ctx, + organizationId + ) + - label: Java SDK + lang: java + source: |- + ScalekitClient scalekitClient = new ScalekitClient( + "", + "", + "" + ); + + Organization organization = scalekitClient.organizations().getById(organizationId); + delete: + description: Remove an existing organization from the environment using its unique identifier + tags: + - Organizations + summary: Delete an organization + operationId: OrganizationService_DeleteOrganization + parameters: + - schema: + type: string + description: Unique scalekit-generated identifier that uniquely references an organization + name: id + in: path + required: true + responses: + '200': + description: Organization successfully deleted and no longer accessible + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: await scalekit.organization.deleteOrganization(organizationId); + - label: Python SDK + lang: python + source: scalekit_client.organization.delete_organization(organization_id) + - label: Go SDK + lang: go + source: |- + err := scalekitClient.Organization.DeleteOrganization( + ctx, + organizationId + ) + - label: Java SDK + lang: java + source: |- + ScalekitClient scalekitClient = new ScalekitClient( + "", + "", + "" + ); + + scalekitClient.organizations().deleteById(organizationId); + patch: + description: Updates an organization's display name, external ID, or metadata. Requires a valid organization identifier. Region code cannot be modified through this endpoint. + tags: + - Organizations + summary: Update organization details + operationId: OrganizationService_UpdateOrganization + parameters: + - schema: + type: string + description: Unique identifier of the organization to be updated + name: id + in: path + required: true + responses: + '200': + description: Returns the updated organization with all current details reflected in the response. + content: + application/json: + schema: + $ref: '#/components/schemas/organizationsUpdateOrganizationResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + const organization = await scalekit.organization.updateOrganization(organization_id, { + displayName: 'displayName', + externalId: 'externalId', + }); + - label: Python SDK + lang: python + source: |- + organization = scalekit_client.organization.update_organization(organization_id, { + display_name: "display_name", + external_id: "external_id" + }) + - label: Go SDK + lang: go + source: |- + organization, err := scalekitClient.Organization.UpdateOrganization( + ctx, + organizationId, + &scalekit.UpdateOrganization{ + DisplayName: "displayName", + ExternalId: "externalId", + }, + ) + - label: Java SDK + lang: java + source: |- + UpdateOrganization updateOrganization = UpdateOrganization.newBuilder() + .setDisplayName("Updated Organization Name") + .build(); + + Organization updatedOrganizationById = scalekitClient.organizations().updateById(organizationId, updateOrganization); + requestBody: + content: + application/json: + schema: + description: Organization Parameters to be updated + $ref: '#/components/schemas/v1organizationsUpdateOrganization' + required: true + /api/v1/organizations/{id}/portal_links: + put: + description: Creates a single use Admin Portal URL valid for 1 minute. Once the generated admin portal URL is accessed or rendered, a temporary session of 6 hours is created to allow the admin to update SSO/SCIM configuration. + tags: + - Organizations + summary: Generate admin portal link + operationId: OrganizationService_GeneratePortalLink + parameters: + - schema: + type: string + description: Organization ID + name: id + in: path + required: true + - schema: + type: array + items: + enum: + - dir_sync + - sso + type: string + style: form + explode: true + description: |- + Features to enable in the admin portal link. To enable features, append them as URL parameters: + + - Single Sign-On: ?features=sso + - Directory Sync: ?features=dir_sync + - Both features: ?features=sso&features=dir_sync + + Example URL: https://scalekit.com/portal/lnk_123?features=sso + + - dir_sync: Enables directory synchronization configuration in the portal + - sso: Enables Single Sign-On (SSO) configuration in the portal + name: features + in: query + responses: + '200': + description: Admin Portal link generated successfully. Returns the portal URL and expiration timestamp. + content: + application/json: + schema: + $ref: '#/components/schemas/organizationsGeneratePortalLinkResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const link = await scalekit.organization.generatePortalLink(organizationId); + - label: Python SDK + lang: python + source: |- + link = scalekit_client.organization.generate_portal_link( + organization_id + ) + - label: Go SDK + lang: go + source: |- + link, err := scalekitClient.Organization.GeneratePortalLink( + ctx, + organizationId + ) + - label: Java SDK + lang: java + source: |- + Link portalLink = client + .organizations() + .generatePortalLink(organizationId, Arrays.asList(Feature.sso, Feature.dir_sync)); + /api/v1/organizations/{id}/settings: + patch: + description: Updates configuration settings for an organization. Supports modifying SSO configuration, directory synchronization settings, and session parameters. Requires organization ID and the specific settings to update. + tags: + - Organizations + summary: Toggle organization settings + operationId: OrganizationService_UpdateOrganizationSettings + parameters: + - schema: + type: string + description: Unique identifier of the organization to update settings. Must begin with 'org_' prefix + name: id + in: path + required: true + responses: + '200': + description: Returns the complete organization object with updated settings applied. Contains all organization details including ID, display name, and the modified settings. + content: + application/json: + schema: + $ref: '#/components/schemas/organizationsGetOrganizationResponse' + '400': + description: Invalid request - occurs when the settings payload contains invalid values or unsupported configuration + content: + application/json: + schema: {} + '404': + description: Organization not found - the specified organization ID doesn't exist + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + const settings = { + features: [ + { + name: 'sso', + enabled: true, + }, + { + name: 'dir_sync', + enabled: true, + }, + ], + }; + + await scalekit.organization.updateOrganizationSettings('', settings); + - label: Python SDK + lang: python + source: |- + settings = [ + { + "name": "sso", + "enabled": True + }, + { + "name": "dir_sync", + "enabled": True + } + ] + + scalekit_client.organization.update_organization_settings( + organization_id='', settings=settings + ) + - label: Go SDK + lang: go + source: "settings := OrganizationSettings{\n\n\t\tFeatures: []Feature{\n\n\t\t\t{\n\n\t\t\t\tName: \"sso\",\n\n\t\t\t\tEnabled: true,\n\n\t\t\t},\n\n\t\t\t{\n\n\t\t\t\tName: \"dir_sync\",\n\n\t\t\t\tEnabled: true,\n\n\t\t\t},\n\n\t\t},\n\n\t}\n\n\norganization,err := scalekitClient.Organization().UpdateOrganizationSettings(ctx, organizationId, settings)" + - label: Java SDK + lang: java + source: |- + OrganizationSettingsFeature featureSSO = OrganizationSettingsFeature.newBuilder() + .setName("sso") + .setEnabled(true) + .build(); + + OrganizationSettingsFeature featureDirectorySync = OrganizationSettingsFeature.newBuilder() + .setName("dir_sync") + .setEnabled(true) + .build(); + + updatedOrganization = scalekitClient.organizations() + .updateOrganizationSettings(organization.getId(), List.of(featureSSO, + featureDirectorySync)); + requestBody: + content: + application/json: + schema: + description: Settings configuration to apply to the organization. Contains feature toggles for SSO, directory synchronization, and other organization capabilities + $ref: '#/components/schemas/organizationsOrganizationSettings' + examples: + - features: + - enabled: true + name: sso + - enabled: false + name: directory_sync + required: true + /api/v1/organizations/{org_id}/roles: + get: + description: Retrieves all environment roles and organization specific roles. Use this endpoint to view all role definitions, including custom roles and their configurations. You can optionally include permission details for each role to understand their capabilities. This is useful for role management, auditing organization access controls, or understanding the available access levels within the organization. + tags: + - Roles + summary: List organization roles + operationId: RolesService_ListOrganizationRoles + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + - schema: + type: string + description: 'Include additional data in the response. Valid values: ''permissions'' (direct permissions only), ''permissions:all'' (includes inherited permissions)' + name: include + in: query + responses: + '200': + description: Successfully retrieved list of organization roles. Returns all roles with their metadata and optionally their permissions. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesListOrganizationRolesResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.role.listOrganizationRoles("org_123"); + - label: Python SDK + lang: python + source: res = scalekit_client.roles.list_organization_roles(org_id="org_123") + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Role().ListOrganizationRoles(ctx, "org_123") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: ListOrganizationRolesResponse res = scalekitClient.roles().listOrganizationRoles("org_123"); + post: + description: Creates a new role within the specified organization with basic configuration including name, display name, description, and permissions. Use this endpoint to define custom roles that can be assigned to users within the organization. You can create hierarchical roles by extending existing roles and assign specific permissions to control access levels. The role will be scoped to the organization and can be used for organization-specific access control. + tags: + - Roles + summary: Create organization role + operationId: RolesService_CreateOrganizationRole + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + responses: + '201': + description: Organization role created successfully. Returns the complete role object with system-generated ID and timestamps. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesCreateOrganizationRoleResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + await scalekit.role.createOrganizationRole("org_123", { + name: "org_admin", + displayName: "Org Admin", + description: "Organization-scoped role", + extends: "base_role_name", // optional + permissions: ["perm.read", "perm.write"] // optional + }); + - label: Python SDK + lang: python + source: |- + from scalekit.v1.roles.roles_pb2 import CreateOrganizationRole + + role = CreateOrganizationRole( + name="org_admin", + display_name="Org Admin", + description="Organization-scoped role", + extends="base_role_name", # optional + permissions=["perm.read", "perm.write"] # optional + ) + + scalekit_client.roles.create_organization_role( + org_id="org_123", + role=role + ) + - label: Go SDK + lang: go + source: "resp, err := scalekitClient.Role().CreateOrganizationRole(ctx, \"org_123\", &rolesv1.CreateOrganizationRole{\n\n\tName: \"org_admin\",\n\n\tDisplayName: \"Org Admin\",\n\n\tDescription: proto.String(\"Organization-scoped role\"), // optional\n\n\tExtends: proto.String(\"base_role_name\"), // optional\n\n\tPermissions: []string{\"perm.read\", \"perm.write\"}, // optional\n\n})" + - label: Java SDK + lang: java + source: |- + CreateOrganizationRoleResponse res = scalekitClient.roles().createOrganizationRole( + "org_123", + CreateOrganizationRoleRequest.newBuilder() + .setOrgId("org_123") + .setRole( + CreateOrganizationRole.newBuilder() + .setName("org_admin") + .setDisplayName("Org Admin") + .setDescription("Organization-scoped role") + .setExtends("base_role_name") // optional + .addPermissions("perm.read") // optional + .addPermissions("perm.write") // optional + .build() + ) + .build() + ); + requestBody: + content: + application/json: + schema: + description: Organization role details + $ref: '#/components/schemas/v1rolesCreateOrganizationRole' + required: true + /api/v1/organizations/{org_id}/roles/{role_name}: + get: + description: Retrieves complete information for a specific organization role including metadata, inheritance details, and optionally permissions. Use this endpoint to audit role configuration and understand the role's place in the organization's role hierarchy. You can include permission details to see what capabilities the role provides. This operation is useful for role management, user assignment decisions, or understanding organization access controls. + tags: + - Roles + summary: Get organization role details + operationId: RolesService_GetOrganizationRole + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + - schema: + type: string + description: Unique name of the role + name: role_name + in: path + required: true + - schema: + type: string + description: 'Include additional data in the response. Valid values: ''permissions'' (direct permissions only), ''permissions:all'' (includes inherited permissions)' + name: include + in: query + responses: + '200': + description: Successfully retrieved organization role details. Returns the role object including metadata and inheritance details. Permissions are included only when requested via the include parameter. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesGetOrganizationRoleResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.role.getOrganizationRole("org_123", "org_admin"); + - label: Python SDK + lang: python + source: |- + res = scalekit_client.roles.get_organization_role( + org_id="org_123", + role_name="org_admin" + ) + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Role().GetOrganizationRole(ctx, "org_123", "org_admin") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: GetOrganizationRoleResponse res = scalekitClient.roles().getOrganizationRole("org_123", "org_admin"); + put: + description: Modifies an existing organization role's properties including display name, description, permissions, and inheritance settings. Use this endpoint to update role metadata, change permission assignments, or modify role hierarchy within the organization. Only the fields you specify will be updated, leaving other properties unchanged. When updating permissions, the new list replaces all existing permissions for the role. + tags: + - Roles + summary: Update organization role + operationId: RolesService_UpdateOrganizationRole + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + - schema: + type: string + description: Unique name of the role + name: role_name + in: path + required: true + responses: + '200': + description: Organization role updated successfully. Returns the modified role object with updated timestamps. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesUpdateOrganizationRoleResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + await scalekit.role.updateOrganizationRole("org_123", "org_admin", { + displayName: "Org Admin (Updated)", + description: "Updated org role description" + }); + - label: Python SDK + lang: python + source: |- + from scalekit.v1.roles.roles_pb2 import UpdateRole + + scalekit_client.roles.update_organization_role( + org_id="org_123", + role_name="org_admin", + role=UpdateRole( + display_name="Org Admin (Updated)", + description="Updated org role description" + ) + ) + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Role().UpdateOrganizationRole(ctx, "org_123", "org_admin", &rolesv1.UpdateRole{ + DisplayName: "Org Admin (Updated)", + Description: "Updated org role description", + }) + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: |- + UpdateOrganizationRoleResponse res = scalekitClient.roles().updateOrganizationRole( + "org_123", + "org_admin", + UpdateOrganizationRoleRequest.newBuilder() + .setRole( + UpdateRole.newBuilder() + .setDisplayName("Org Admin (Updated)") + .setDescription("Updated org role description") + .build() + ) + .build() + ); + requestBody: + content: + application/json: + schema: + description: Organization role details + $ref: '#/components/schemas/v1rolesUpdateRole' + required: true + delete: + description: Permanently removes a role from the organization and optionally reassigns users who had that role to a different role. Use this endpoint when you need to clean up unused roles or restructure your organization's access control system. If users are assigned to the role being deleted, you can provide a reassign_role_name to move those users to a different role before deletion. This action cannot be undone, so ensure no critical users depend on the role before deletion. + tags: + - Roles + summary: Delete organization role + operationId: RolesService_DeleteOrganizationRole + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + - schema: + type: string + description: Unique name of the role + name: role_name + in: path + required: true + - schema: + type: string + description: Role name to reassign users to when deleting this role + name: reassign_role_name + in: query + responses: + '200': + description: Organization role successfully deleted and users reassigned if specified. No content returned. + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + // Basic delete + await scalekit.role.deleteOrganizationRole("org_123", "org_role_admin"); + + // With reassignment + await scalekit.role.deleteOrganizationRole("org_123", "org_role_admin", "org_role_member"); + - label: Python SDK + lang: python + source: |- + # Basic delete + scalekit_client.roles.delete_organization_role( + org_id="org_123", + role_name="org_role_admin" + ) + + # With reassignment + scalekit_client.roles.delete_organization_role( + org_id="org_123", + role_name="org_role_admin", + reassign_role_name="org_role_member" + ) + - label: Go SDK + lang: go + source: |- + // Basic delete + err := scalekitClient.Role().DeleteOrganizationRole(ctx, "org_123", "org_role_admin") + if err != nil { /* handle err */ } + + // With reassignment + err = scalekitClient.Role().DeleteOrganizationRole(ctx, "org_123", "org_role_admin", "org_role_member") + - label: Java SDK + lang: java + source: |- + // Basic delete + scalekitClient.roles().deleteOrganizationRole("org_123", "org_role_admin"); + + // With reassignment + scalekitClient.roles().deleteOrganizationRole("org_123", "org_role_admin", "org_role_member"); + /api/v1/organizations/{org_id}/roles:set_defaults: + patch: + description: Updates the default member role for the specified organization. Use this endpoint to configure which role is automatically assigned to new users when they join the organization. The system will validate that the specified role exists and update the organization settings accordingly. This configuration affects all new user invitations and memberships within the organization. + tags: + - Roles + summary: Set default organization roles + operationId: RolesService_UpdateDefaultOrganizationRoles + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: org_id + in: path + required: true + responses: + '200': + description: Default organization roles updated successfully. Returns the updated default member role object with complete role information. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesUpdateDefaultOrganizationRolesResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + const res = await scalekit.role.updateDefaultOrganizationRoles("org_123", { + defaultMemberRole: "org_member" + }); + - label: Python SDK + lang: python + source: |- + from scalekit.v1.roles.roles_pb2 import UpdateDefaultOrganizationRolesRequest + + res = scalekit_client.roles.update_default_organization_roles( + org_id="org_123", + default_roles=UpdateDefaultOrganizationRolesRequest( + default_member_role="org_member" + ) + ) + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Role().UpdateDefaultOrganizationRoles(ctx, "org_123", "org_member") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: |- + UpdateDefaultOrganizationRolesResponse res = scalekitClient.roles().updateDefaultOrganizationRoles( + "org_123", + UpdateDefaultOrganizationRolesRequest.newBuilder() + .setDefaultMemberRole("org_member") + .build() + ); + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RolesServiceUpdateDefaultOrganizationRolesBody' + required: true + /api/v1/organizations/{organization_id}/clients: + get: + description: Retrieves a paginated list of API clients for a specific organization. Returns client details including metadata, scopes, and secret information (without exposing actual secret values). + tags: + - API Auth + summary: List organization API clients + operationId: ClientService_ListOrganizationClients + parameters: + - schema: + type: string + description: Unique identifier of the organization whose clients to list. Must start with 'org_' prefix. + name: organization_id + in: path + required: true + - schema: + type: integer + format: int64 + description: |- + Maximum number of clients to return per page + + Maximum number of API clients to return per page. Must be between 10 and 100 + name: page_size + in: query + - schema: + type: string + description: |- + Pagination token from the previous response + + Pagination token from the previous response. Use to retrieve the next page of organization clients + name: page_token + in: query + responses: + '200': + description: List of organization API clients returned successfully. Each client includes its configuration details and metadata. + content: + application/json: + schema: + $ref: '#/components/schemas/clientsListOrganizationClientsResponse' + x-codeSamples: + - label: Python SDK + lang: python + source: |- + # List clients for a specific organization + org_id = 'SCALEKIT_ORGANIZATION_ID' + + # Retrieve all clients with default pagination + response = scalekit_client.m2m_client.list_organization_clients( + organization_id=org_id, + page_size=30 + ) + + # Access the clients list + clients = response.clients + for client in clients: + print(f"Client ID: {scalekit_client.id}, Name: {scalekit_client.name}") + post: + description: Creates a new API client for an organization. Returns the client details and a plain secret (available only once). + tags: + - API Auth + summary: Create organization API client + operationId: ClientService_CreateOrganizationClient + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + responses: + '201': + description: API client created successfully. Returns the client ID and plain secret (only available at creation time). The client can be configured with scopes, audience values, and custom claims for fine-grained access control. + content: + application/json: + schema: + $ref: '#/components/schemas/clientsCreateOrganizationClientResponse' + x-codeSamples: + - label: Python SDK + lang: python + source: |- + from scalekit.v1.clients.clients_pb2 import OrganizationClient + + m2m_client = OrganizationClient( + name="GitHub Actions Deployment Service", + description="Service account for GitHub Actions to deploy applications + to production", + custom_claims=[ + {"key": "github_repository", "value": "acmecorp/inventory-service"}, + {"key": "environment", "value": "production_us"} + ], + scopes=["deploy:applications", "read:deployments"], + audience=["deployment-api.acmecorp.com"], + expiry=3600 + ) + + response = scalekit_client.m2m_client.create_organization_client( + organization_id="SCALEKIT_ORGANIZATION_ID", + m2m_client=m2m_client + ) + requestBody: + content: + application/json: + schema: + description: Details of the client to be created + $ref: '#/components/schemas/clientsOrganizationClient' + required: true + /api/v1/organizations/{organization_id}/clients/{client_id}: + get: + description: Retrieves details of a specific API client in an organization. + tags: + - API Auth + summary: Get organization API client + operationId: ClientService_GetOrganizationClient + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the API client + name: client_id + in: path + required: true + responses: + '200': + description: Returns the complete API client configuration, including all current settings and a list of active secrets. Note that secret values are not included in the response for security reasons. + content: + application/json: + schema: + $ref: '#/components/schemas/clientsGetOrganizationClientResponse' + x-codeSamples: + - label: Python SDK + lang: python + source: |- + # Get client ID from environment variables + org_id = 'SCALEKIT_ORGANIZATION_ID' + client_id = os.environ['M2M_CLIENT_ID'] + + # Fetch client details for the specified organization + response = scalekit_client.m2m_client.get_organization_client( + organization_id=org_id, + client_id=client_id + ) + delete: + description: Permanently deletes an API client from an organization. This operation cannot be undone and will revoke all access for the client. All associated secrets will also be invalidated. Use this endpoint to remove unused or compromised clients. + tags: + - API Auth + summary: Delete organization API client + operationId: ClientService_DeleteOrganizationClient + parameters: + - schema: + type: string + description: Unique identifier of the organization that owns the client. Must start with 'org_' prefix. + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the API client to permanently delete. Must start with 'm2morg_' prefix. + name: client_id + in: path + required: true + responses: + '200': + description: Organization API client successfully deleted and no longer accessible + content: + application/json: + schema: {} + x-codeSamples: + - label: Python SDK + lang: python + source: |- + # Get client ID from environment variables + org_id = '' + client_id = os.environ['M2M_CLIENT_ID'] + + # Delete the specified client from the organization + response = scalekit_client.m2m_client.delete_organization_client( + organization_id=org_id, + client_id=client_id + ) + patch: + description: Updates an existing organization API client. Only specified fields are modified. + tags: + - API Auth + summary: Update organization API client + operationId: ClientService_UpdateOrganizationClient + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the client + name: client_id + in: path + required: true + responses: + '200': + description: Returns the updated organization API client with all current details reflected in the response, including modified scopes, audience values, and custom claims. + content: + application/json: + schema: + $ref: '#/components/schemas/clientsUpdateOrganizationClientResponse' + x-codeSamples: + - label: Python SDK + lang: python + source: |- + from scalekit.v1.clients.clients_pb2 import OrganizationClient + + org_id = '' + client_id = os.environ['M2M_CLIENT_ID'] + + update_m2m_client = OrganizationClient( + description="Service account for GitHub Actions to deploy applications + to production_eu", + custom_claims=[ + {"key": "github_repository", "value": "acmecorp/inventory"}, + {"key": "environment", "value": "production_eu"} + ] + ) + + response = scalekit_client.m2m_client.update_organization_client( + organization_id=org_id, + client_id=client_id, + m2m_client=update_m2m_client + ) + requestBody: + content: + application/json: + schema: + description: Updated details for the client + $ref: '#/components/schemas/clientsOrganizationClient' + required: true + /api/v1/organizations/{organization_id}/clients/{client_id}/secrets: + post: + description: Creates a new secret for an organization API client. Returns the plain secret (available only once). + tags: + - API Auth + summary: Create organization API client secret + operationId: ClientService_CreateOrganizationClientSecret + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the API client + name: client_id + in: path + required: true + responses: + '201': + description: Client secret created successfully. Returns the new secret ID and the plain secret value (only available at creation time). The secret can be used immediately for authentication. + content: + application/json: + schema: + $ref: '#/components/schemas/clientsCreateOrganizationClientSecretResponse' + x-codeSamples: + - label: Python SDK + lang: python + source: |- + # Get client ID from environment variables + org_id = 'SCALEKIT_ORGANIZATION_ID' + client_id = os.environ['M2M_CLIENT_ID'] + + # Add a new secret to the specified client + response = scalekit_client.m2m_client.add_organization_client_secret( + organization_id=org_id, + client_id=client_id + ) + + # Extract the secret ID from the response + secret_id = response[0].secret.id + /api/v1/organizations/{organization_id}/clients/{client_id}/secrets/{secret_id}: + delete: + description: Permanently deletes a secret from an organization API client. This operation cannot be undone. + tags: + - API Auth + summary: Delete organization API client secret + operationId: ClientService_DeleteOrganizationClientSecret + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the API client + name: client_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the client secret + name: secret_id + in: path + required: true + responses: + '200': + description: Client secret successfully deleted and no longer accessible + content: + application/json: + schema: {} + x-codeSamples: + - label: Python SDK + lang: python + source: |- + # Get client and secret IDs from environment variables + org_id = '' + client_id = os.environ['M2M_CLIENT_ID'] + secret_id = os.environ['M2M_SECRET_ID'] + + # Remove the specified secret from the client + response = scalekit_client.m2m_client.remove_organization_client_secret( + organization_id=org_id, + client_id=client_id, + secret_id=secret_id + ) + /api/v1/organizations/{organization_id}/connections/{id}: + get: + description: Retrieves the complete configuration and status details for a specific connection by its ID within an organization. Returns all connection properties including provider settings, protocols, and current status. + tags: + - Connections + summary: Get connection details + operationId: ConnectionService_GetConnection + parameters: + - schema: + type: string + description: Organization identifier (required). Specifies which organization owns the connection you want to retrieve. + name: organization_id + in: path + required: true + - schema: + type: string + description: Connection identifier (required). Specifies which specific connection to retrieve from the organization. + name: id + in: path + required: true + responses: + '200': + description: Successfully retrieved connection details for the specified organization + content: + application/json: + schema: + $ref: '#/components/schemas/connectionsGetConnectionResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + const connection = await scalekit.connection.getConnection( + organizationId, + connectionId + ); + - label: Python SDK + lang: python + source: |- + connection = scalekit_client.connection.get_connection( + organization_id, + connection_id, + ) + - label: Go SDK + lang: go + source: |- + connection, err := scalekitClient.Connection.GetConnection( + ctx, + organizationId, + connectionId, + ) + - label: Java SDK + lang: java + source: Connection connection = scalekitClient.connections().getConnectionById(connectionId, organizationId); + delete: + description: Deletes an SSO connection from the specified organization by connection ID. Use this endpoint when an identity provider integration is no longer needed for the organization. Returns an empty response after the SSO connection is deleted successfully. + tags: + - Connections + summary: Delete SSO connection + operationId: ConnectionService_DeleteConnection + parameters: + - schema: + type: string + description: Organization ID for the Connection. + name: organization_id + in: path + required: true + - schema: + type: string + description: Connection ID. Unique ID for the connection + name: id + in: path + required: true + responses: + '200': + description: SSO connection deleted successfully + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: await scalekit.connection.deleteConnection(organizationId, connectionId); + - label: Python SDK + lang: python + source: |- + scalekit_client.connection.delete_connection( + organization_id, + connection_id + ) + - label: Go SDK + lang: go + source: |- + err := scalekitClient.Connection.DeleteConnection( + ctx, + organizationId, + connectionId, + ) + - label: Java SDK + lang: java + source: scalekitClient.connections().deleteConnection(connectionId, organizationId); + /api/v1/organizations/{organization_id}/connections/{id}:disable: + patch: + description: Deactivate an existing connection for the specified organization. When disabled, users cannot authenticate using this connection. This endpoint changes the connection state from enabled to disabled without modifying other configuration settings + tags: + - Connections + summary: Disable SSO connection + operationId: ConnectionService_DisableConnection + parameters: + - schema: + type: string + description: Unique identifier of the organization associated with the connection + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier for the connection to be toggled + name: id + in: path + required: true + responses: + '200': + description: Connection disabled successfully + content: + application/json: + schema: + $ref: '#/components/schemas/connectionsToggleConnectionResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: await scalekit.connection.disableConnection(organizationId, connectionId); + - label: Python SDK + lang: python + source: |- + scalekit_client.connection.disable_connection( + organization_id, + connection_id + ) + - label: Go SDK + lang: go + source: |- + err := scalekitClient.Connection.DisableConnection( + ctx, + organizationId, + connectionId, + ) + - label: Java SDK + lang: java + source: ToggleConnectionResponse response = scalekitClient.connections().disableConnection(connectionId, organizationId); + /api/v1/organizations/{organization_id}/connections/{id}:enable: + patch: + description: Activate an existing connection for the specified organization. When enabled, users can authenticate using this connection. This endpoint changes the connection state from disabled to enabled without modifying other configuration settings + tags: + - Connections + summary: Enable SSO connection + operationId: ConnectionService_EnableConnection + parameters: + - schema: + type: string + description: Unique identifier of the organization associated with the connection + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier for the connection to be toggled + name: id + in: path + required: true + responses: + '200': + description: Connection enabled successfully + content: + application/json: + schema: + $ref: '#/components/schemas/connectionsToggleConnectionResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: await scalekit.connection.enableConnection(organizationId, connectionId); + - label: Python SDK + lang: python + source: |- + scalekit_client.connection.enable_connection( + organization_id, + connection_id, + ) + - label: Go SDK + lang: go + source: |- + err := scalekitClient.Connection.EnableConnection( + ctx, + organizationId, + connectionId, + ) + - label: Java SDK + lang: java + source: ToggleConnectionResponse response = scalekitClient.connections().enableConnection(connectionId, organizationId); + /api/v1/organizations/{organization_id}/directories: + get: + tags: + - Directory + summary: List organization directories + operationId: DirectoryService_ListDirectories + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + responses: + '200': + description: Successfully retrieved the list of directories for the organization + content: + application/json: + schema: + $ref: '#/components/schemas/directoriesListDirectoriesResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: await scalekit.directory.listDirectories(''); + - label: Python SDK + lang: python + source: "directories_list = scalekit_client.directory.list_directories(\n\torganization_id=''\n)" + - label: Go SDK + lang: go + source: directories,err := scalekitClient.Directory().ListDirectories(ctx, organizationId) + - label: Java SDK + lang: java + source: ListDirectoriesResponse response = scalekitClient.directories().listDirectories(organizationId); + /api/v1/organizations/{organization_id}/directories/{directory_id}/groups: + get: + description: Retrieves all groups from a specified directory. Use this endpoint to view group structures from your connected identity provider. + tags: + - Directory + summary: List directory groups + operationId: DirectoryService_ListDirectoryGroups + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the directory + name: directory_id + in: path + required: true + - schema: + type: integer + format: int64 + description: Number of groups to return per page. Maximum value is 30. If not specified, defaults to 10 + name: page_size + in: query + - schema: + type: string + description: Token for pagination. Use the value returned in the 'next_page_token' field of the previous response + name: page_token + in: query + - schema: + type: string + format: date-time + description: Filter groups updated after this timestamp. Use ISO 8601 format + name: updated_after + in: query + - schema: + type: boolean + description: If true, includes full group details. If false or not specified, returns basic information only + name: include_detail + in: query + - schema: + type: boolean + description: 'If true, returns group and its details from external provider (default: false)' + name: include_external_groups + in: query + responses: + '200': + description: Successfully retrieved the list of groups from the specified directory + content: + application/json: + schema: + $ref: '#/components/schemas/directoriesListDirectoryGroupsResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + const { groups } = await scalekit.directory.listDirectoryGroups( + '', + '' + ); + - label: Python SDK + lang: python + source: |- + directory_groups = scalekit_client.directory.list_directory_groups( + directory_id='', organization_id='' + ) + - label: Go SDK + lang: go + source: "options := &ListDirectoryGroupsOptions{\n\n\t\tPageSize: 10,\n\n\t\tPageToken:\"\",\n\n\t}\n\n\ndirectoryGroups, err := scalekitClient.Directory().ListDirectoryGroups(ctx, organizationId, directoryId, options)" + - label: Java SDK + lang: java + source: |- + var options = ListDirectoryResourceOptions.builder() + .pageSize(10) + .pageToken("") + .includeDetail(true) + .build(); + + ListDirectoryGroupsResponse groupsResponse = scalekitClient + .directories() + .listDirectoryGroups(directory.getId(), organizationId, options); + /api/v1/organizations/{organization_id}/directories/{directory_id}/users: + get: + description: Retrieves a list of all users within a specified directory for an organization. This endpoint allows you to view user accounts associated with your connected Directory Providers. + tags: + - Directory + summary: List directory users + operationId: DirectoryService_ListDirectoryUsers + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the directory within the organization + name: directory_id + in: path + required: true + - schema: + type: integer + format: int64 + description: Number of users to return per page. Maximum value is 30. If not specified, defaults to 10 + name: page_size + in: query + - schema: + type: string + description: Token for pagination. Use the value returned in the 'next_page_token' field of the previous response to retrieve the next page of results + name: page_token + in: query + - schema: + type: boolean + description: If set to true, the response will include the full user payload with all available details. If false or not specified, only essential user information will be returned + name: include_detail + in: query + - schema: + type: string + description: Filter users by their membership in a specific directory group + name: directory_group_id + in: query + - schema: + type: string + format: date-time + description: Filter users that were updated after the specified timestamp. Use ISO 8601 format + name: updated_after + in: query + responses: + '200': + description: Successfully retrieved the list of users from the specified directory + content: + application/json: + schema: + $ref: '#/components/schemas/directoriesListDirectoryUsersResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + const { users } = await scalekit.directory.listDirectoryUsers( + '', + '' + ); + - label: Python SDK + lang: python + source: |- + directory_users = scalekit_client.directory.list_directory_users( + directory_id='', organization_id='' + ) + - label: Go SDK + lang: go + source: "options := &ListDirectoryUsersOptions{\n\n\t\tPageSize: 10,\n\n\t\tPageToken: \"\",\n\n\t}\n\ndirectoryUsers,err := scalekitClient.Directory().ListDirectoryUsers(ctx, organizationId, directoryId, options)" + - label: Java SDK + lang: java + source: |- + var options = ListDirectoryResourceOptions.builder() + .pageSize(10) + .pageToken("") + .includeDetail(true) + .build(); + + ListDirectoryUsersResponse usersResponse = scalekitClient + .directories() + .listDirectoryUsers(directory.getId(), organizationId, options); + /api/v1/organizations/{organization_id}/directories/{id}: + get: + description: Retrieves detailed information about a specific directory within an organization + tags: + - Directory + summary: Get directory details + operationId: DirectoryService_GetDirectory + parameters: + - schema: + type: string + description: Unique identifier of the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier of the directory + name: id + in: path + required: true + responses: + '200': + description: Successfully retrieved directory details + content: + application/json: + schema: + $ref: '#/components/schemas/directoriesGetDirectoryResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + const { directory } = await scalekit.directory.getDirectory( + organizationId, + directoryId + ); + - label: Python SDK + lang: python + source: |- + directory = scalekit_client.directory.get_directory( + directory_id='', organization_id='' + ) + print(f'Directory details: {directory}') + - label: Go SDK + lang: go + source: directory, err := scalekitClient.Directory().GetDirectory(ctx, organizationId, directoryId) + - label: Java SDK + lang: java + source: Directory directory = scalekitClient.directories().getDirectory(directoryId, organizationId); + /api/v1/organizations/{organization_id}/directories/{id}:disable: + patch: + description: Stops synchronization of users and groups from a specified directory within an organization. This operation prevents further updates from the connected Directory provider + tags: + - Directory + summary: Disable a directory + operationId: DirectoryService_DisableDirectory + parameters: + - schema: + type: string + description: A unique identifier for the organization. The value must begin with 'org_' and be between 1 and 32 characters long + name: organization_id + in: path + required: true + - schema: + type: string + description: A unique identifier for a directory within the organization. The value must begin with 'dir_' and be between 1 and 32 characters long + name: id + in: path + required: true + responses: + '200': + description: Successfully disabled the directory + content: + application/json: + schema: + $ref: '#/components/schemas/directoriesToggleDirectoryResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + await scalekit.directory.disableDirectory( + '', + '' + ); + - label: Python SDK + lang: python + source: |- + directory_response = scalekit_client.directory.disable_directory( + directory_id='', organization_id='' + ) + - label: Go SDK + lang: go + source: disable,err := scalekitClient.Directory().DisableDirectory(ctx, organizationId, directoryId) + - label: Java SDK + lang: java + source: |- + ToggleDirectoryResponse disableResponse = scalekitClient + .directories() + .disableDirectory(directoryId, organizationId); + /api/v1/organizations/{organization_id}/directories/{id}:enable: + patch: + description: Activates a directory within an organization, allowing it to synchronize users and groups with the connected Directory provider + tags: + - Directory + summary: Enable a directory + operationId: DirectoryService_EnableDirectory + parameters: + - schema: + type: string + description: A unique identifier for the organization. The value must begin with 'org_' and be between 1 and 32 characters long + name: organization_id + in: path + required: true + - schema: + type: string + description: A unique identifier for a directory within the organization. The value must begin with 'dir_' and be between 1 and 32 characters long + name: id + in: path + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/directoriesToggleDirectoryResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: await scalekit.directory.enableDirectory('', ''); + - label: Python SDK + lang: python + source: |- + directory_response = scalekit_client.directory.enable_directory( + directory_id='', organization_id='' + ) + - label: Go SDK + lang: go + source: enable,err := scalekitClient.Directory().EnableDirectory(ctx, organizationId, directoryId) + - label: Java SDK + lang: java + source: |- + ToggleDirectoryResponse enableResponse = client + .directories() + .enableDirectory(directoryId, organizationId); + /api/v1/organizations/{organization_id}/domains: + get: + description: |+ + Retrieves a paginated list of all domains configured for the specified organization. + + Domain types: + - ALLOWED_EMAIL_DOMAIN: Trusted domains used to suggest the organization in the organization switcher during sign-in/sign-up (auth-method agnostic). + - ORGANIZATION_DOMAIN: SSO discovery domains used to route users to the correct SSO provider and enforce SSO. + + tags: + - Domains + summary: List Domains + operationId: DomainService_ListDomains + parameters: + - schema: + type: string + description: Scalekit-generated unique identifier for the organization. Use either this or external_id to identify the organization. + name: organization_id + in: path + required: true + - schema: + type: string + description: Optional comma-separated list of additional fields to include in the response (e.g., 'verification_details'). + name: include + in: query + - schema: + type: integer + format: int32 + description: Maximum number of domains to return per page. Default is 30, maximum is 100. + name: page_size + in: query + - schema: + type: integer + format: int32 + description: Page number to retrieve (0-based). Use 0 for the first page. + name: page_number + in: query + - schema: + type: string + enum: + - ALLOWED_EMAIL_DOMAIN + - ORGANIZATION_DOMAIN + description: | + The domain type. + - ALLOWED_EMAIL_DOMAIN: trusted domain used to suggest the organization in the organization switcher during sign-in/sign-up. + - ORGANIZATION_DOMAIN: SSO discovery domain used to route users to the correct SSO provider and enforce SSO. + name: domain_type + in: query + responses: + '200': + description: Successfully retrieved the list of domains. + content: + application/json: + schema: + $ref: '#/components/schemas/domainsListDomainResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: "// List all domains in an organization\nconst response = await scalekit.domain.listDomains(organizationId, {\n\tdomainType: \"ORGANIZATION_DOMAIN\"\n});\n\n// Domain object contains:\n// - id: Domain identifier\n// - domain: Domain name\n// - organizationId: Owning organization\n// - domainType: Configuration type" + - label: Python SDK + lang: python + source: |- + # List all domains in an organization + response = scalekit_client.domain.list_domains( + organization_id="org_123", + domain_type="ORGANIZATION_DOMAIN" + ) + # - organization_id: Owning organization + # - domain_type: domain type + - label: Go SDK + lang: go + source: |- + domains, err := scalekitClient.Domain().ListDomains(ctx, "org_id", &scalekit.ListDomainOptions{ + DomainType: "ORGANIZATION_DOMAIN", + }) + - label: Java SDK + lang: java + source: List domains = scalekitClient.domains().listDomainsByOrganizationId("org_id", "ORGANIZATION_DOMAIN"); + post: + description: |+ + Creates and associates a domain with an organization. + + Use one of the following domain types: + - ALLOWED_EMAIL_DOMAIN: Adds a trusted email domain for organization suggestions in the organization switcher during sign-in/sign-up (auth-method agnostic). + - ORGANIZATION_DOMAIN: Enables SSO domain discovery. If a user signs in with a matching email domain, Scalekit redirects them to the organization’s SSO provider and enforces SSO. + + The domain must be a valid business domain that you control. Public/disposable domains (e.g., gmail.com) are blocked for security. + + tags: + - Domains + summary: Create Domain + operationId: DomainService_CreateDomain + parameters: + - schema: + type: string + description: Scalekit-generated unique identifier for the organization. Use either this or external_id to identify the organization. + name: organization_id + in: path + required: true + responses: + '200': + description: Successfully created the domain. + content: + application/json: + schema: + $ref: '#/components/schemas/domainsCreateDomainResponse' + '400': + description: Invalid request — common causes invalid domain format, public or disposable domain, or domain already exists. + content: + application/json: + schema: + $ref: '#/components/schemas/errdetailsErrorInfo' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: "// Add a new domain to an organization\nconst response = await scalekit.createDomain(\"org-123\", \"example.com\", {\n\n\t// Domain type: controls user authentication and email validation\n\n\tdomainType: \"ORGANIZATION_DOMAIN\",\n\n});" + - label: Python SDK + lang: python + source: "# Add a new domain to an organization\nresponse = scalekit_client.domain.create_domain(organization_id=\"org-123\",\n\n\t\t\tdomain_name=\"example.com\",\n \t\t\tdomain_type=\"ORGANIZATION_DOMAIN\")" + - label: Go SDK + lang: go + source: "domain, err := scalekitClient.Domain().CreateDomain(ctx, \"org_id\", \"example.com\", &scalekit.CreateDomainOptions{\n\n\t\tDomainType: \"ORGANIZATION_DOMAIN\",\n\n\t})" + - label: Java SDK + lang: java + source: "CreateDomainRequest request = CreateDomainRequest.newBuilder()\n\t.setOrganizationId(organization.getId())\n\t.setDomain(CreateDomain.newBuilder()\n\t\t.setDomain(\"example.com\")\n\t\t.setDomainType(\"ORGANIZATION_DOMAIN\")\n\t\t.build())\n\t.build();\n\t\nDomain domain = scalekitClient.domains().createDomain(request);" + requestBody: + content: + application/json: + schema: + description: Domain configuration including the domain name and type. + $ref: '#/components/schemas/v1domainsCreateDomain' + required: true + /api/v1/organizations/{organization_id}/domains/{id}: + get: + description: |+ + Retrieves complete details for a domain including domain type, timestamps, and configuration information. + + tags: + - Domains + summary: Get Domain + operationId: DomainService_GetDomain + parameters: + - schema: + type: string + description: Scalekit-generated unique identifier for the organization. Use either this or external_id to identify the organization. + name: organization_id + in: path + required: true + - schema: + type: string + description: Scalekit-generated unique identifier of the domain to retrieve. + name: id + in: path + required: true + responses: + '200': + description: Successfully retrieved the domain details. + content: + application/json: + schema: + $ref: '#/components/schemas/domainsGetDomainResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + // Fetch details of a specific domain + const response = await scalekit.domain.getDomain(organizationId, domainId); + + // Domain object properties: + // - id: Domain identifier + // - domain: Domain name + // - organizationId: Owning organization + // - domainType: Domain configuration type + - label: Python SDK + lang: python + source: |- + # Fetch details of a specific domain + response = scalekit_client.domain.get_domain(organization_id="org_123", domain_id="dom_123") + - label: Go SDK + lang: go + source: domain, err := scalekitClient.Domain().GetDomain(ctx, "dom_123", "org_123") + - label: Java SDK + lang: java + source: Domain domain = scalekitClient.domains().getDomainById("org_123", "dom_123"); + delete: + description: |+ + Permanently removes a domain record from an organization. + + - Deleting an ORGANIZATION_DOMAIN disables SSO routing/enforcement for that domain. + - Deleting an ALLOWED_EMAIL_DOMAIN stops organization suggestions for users with that email domain. + + tags: + - Domains + summary: Delete Domain + operationId: DomainService_DeleteDomain + parameters: + - schema: + type: string + description: Scalekit-generated unique identifier for the organization. Use either this or external_id to identify the organization. + name: organization_id + in: path + required: true + - schema: + type: string + description: Scalekit-generated unique identifier of the domain to be permanently deleted. + name: id + in: path + required: true + responses: + '200': + description: Domain successfully deleted. + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + // Remove a domain from an organization + // Caution: Deletion is permanent and may affect user access + const response = await scalekit.domain.deleteDomain(organizationId, domainId); + - label: Python SDK + lang: python + source: |- + # Remove a domain from an organization + # Caution: Deletion is permanent and may affect user access + response = scalekit_client.domain.delete_domain( + organization_id="org_123", + domain_id="dom_123" + ) + - label: Go SDK + lang: go + source: err = scalekitClient.Domain().DeleteDomain(ctx, "dom_123", "org_123") + - label: Java SDK + lang: java + source: scalekitClient.domains().deleteDomain(organization.getId(), domain.getId()); + /api/v1/organizations/{organization_id}/session-policy: + get: + description: Retrieves the session policy for an organization. Returns session_policy='APPLICATION' if the organization inherits the application-level defaults, or session_policy='CUSTOM' with the configured values if a custom policy is active. + tags: + - Organizations + summary: Get organization session policy + operationId: OrganizationService_GetOrganizationSessionPolicy + parameters: + - schema: + type: string + description: The unique identifier of the organization whose session policy is being requested. + name: organization_id + in: path + required: true + responses: + '200': + description: Session policy retrieved successfully. + content: + application/json: + schema: + $ref: '#/components/schemas/organizationsGetOrganizationSessionPolicyResponse' + '404': + description: Organization not found. + content: + application/json: + schema: {} + patch: + description: Sets a custom session policy for an organization or reverts to application-level settings. Send session_policy='APPLICATION' to revert to application defaults. Send session_policy='CUSTOM' with timeout values to activate a custom policy. + tags: + - Organizations + summary: Update organization session policy + operationId: OrganizationService_UpdateOrganizationSessionPolicy + parameters: + - schema: + type: string + description: The unique identifier of the organization whose session policy is being updated. + name: organization_id + in: path + required: true + responses: + '200': + description: Session policy updated successfully. + content: + application/json: + schema: + $ref: '#/components/schemas/organizationsUpdateOrganizationSessionPolicyResponse' + '404': + description: Organization not found. + content: + application/json: + schema: {} + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationServiceUpdateOrganizationSessionPolicyBody' + required: true + /api/v1/organizations/{organization_id}/settings/usermanagement: + patch: + description: Upsert user management settings for an organization + tags: + - Organizations + summary: Upsert organization user setting + operationId: OrganizationService_UpsertUserManagementSettings + parameters: + - schema: + type: string + description: ID of the organization. + name: organization_id + in: path + required: true + responses: + '200': + description: Returns the updated organization setting. + content: + application/json: + schema: + $ref: '#/components/schemas/organizationsUpsertUserManagementSettingsResponse' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationServiceUpsertUserManagementSettingsBody' + required: true + /api/v1/organizations/{organization_id}/users: + get: + description: Retrieves a paginated list of all users who are members of the specified organization. Use this endpoint to view all users with access to a particular organization, including their roles, metadata, and membership details. Supports pagination for large user lists. + tags: + - Users + summary: List organization users + operationId: UserService_ListOrganizationUsers + parameters: + - schema: + type: string + description: Unique identifier of the organization for which to list users. Must start with 'org_' and be 1-32 characters long. + name: organization_id + in: path + required: true + - schema: + type: integer + format: int64 + description: 'Maximum number of users to return in a single response. Valid range: 1-100. Server may return fewer users than specified.' + name: page_size + in: query + - schema: + type: string + description: Pagination token from a previous ListUserResponse. Used to retrieve the next page of results. Leave empty for the first request. + name: page_token + in: query + responses: + '200': + description: Successfully retrieved the list of users in the organization + content: + application/json: + schema: + $ref: '#/components/schemas/usersListOrganizationUsersResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: "const response = await scalekit.user.\n listOrganizationUsers(\"org_123\", {\n\tpageSize: 50,\n});\nconsole.log(response.users);" + - label: Python SDK + lang: python + source: resp, _ = scalekit_client.users.list_users(organization_id="org_123", page_size=50) + - label: Go SDK + lang: go + source: |- + list, + err := scalekitClient.User().ListOrganizationUsers(ctx, "org_123", &scalekit.ListUsersOptions{PageSize: + 50}) if err != nil { /* handle error */ } + fmt.Println(list.Users) + - label: Java SDK + lang: java + source: |- + ListOrganizationUsersRequest listReq = ListOrganiz + ationUsersRequest.newBuilder() + .setPageSize(50) + .build(); + ListOrganizationUsersResponse list = users. + listOrganizationUsers("org_123", listReq); + post: + description: Creates a new user account and immediately adds them to the specified organization. Use this endpoint when you want to create a user and grant them access to an organization in a single operation. You can provide user profile information, assign roles, and configure membership metadata. The user receives an activation email unless this feature is disabled in the organization settings. + tags: + - Users + summary: Create new user in organization + operationId: UserService_CreateUserAndMembership + parameters: + - schema: + type: string + name: organization_id + in: path + required: true + - schema: + type: boolean + description: If true, sends an activation email to the user. Defaults to true. + name: send_invitation_email + in: query + responses: + '201': + description: User created successfully. Returns the created user object, including system-generated identifiers and timestamps + content: + application/json: + schema: + $ref: '#/components/schemas/usersCreateUserAndMembershipResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: "const {\n user } = await scalekit.user.\n createUserAndMembership(\"org_123\", {\n\temail: \"user@example.com\",\n\texternalId: \"ext_12345a67b89c\",\n\tmetadata: { department: \"engineering\", \n\t location: \"nyc-office\" },\n\tuserProfile: {\n\t\tfirstName: \"John\",\n\t\tlastName: \"Doe\",\n\t},\n});" + - label: Python SDK + lang: python + source: |- + # Create user with membership + user = CreateUser( + email="john.doe@example.com", + external_id="ext_john_123", # Optional + user_profile={ + "first_name": "John", + "last_name": "Doe", + "name": "John Doe", + "locale": "en-US", + "phone_number": "+14155552671" + }, + membership={ + "roles": [{"name": "member"}] + } + ) + + # Create user and membership in organization + response = scalekit_client.users.create_user_and_membership( + organization_id="your_org_id", + user=user, + send_invitation_email=True # Set to False if you don't want to send + email ) + + user_id = response[0].user.id + - label: Go SDK + lang: go + source: |- + newUser := &usersv1.CreateUser{ + Email: "user@example.com", + ExternalId: "ext_12345a67b89c", + Metadata: map[string]string{ + "department": "engineering", + "location": "nyc-office", + }, + UserProfile: &usersv1.CreateUserProfile{ + FirstName: "John", + LastName: "Doe", + }, + } + cuResp, + err := scalekitClient.User().CreateUserAndMembership(ctx, "org_123", + newUser, false) if err != nil { /* handle error */ } + - label: Java SDK + lang: java + source: |- + CreateUser createUser = CreateUser.newBuilder() + .setEmail("user@example.com") + .setExternalId("ext_12345a67b89c") + .putMetadata("department", "engineering") + .putMetadata("location", "nyc-office") + .setUserProfile( + CreateUserProfile.newBuilder() + .setFirstName("John") + .setLastName("Doe") + .build()) + .build(); + CreateUserAndMembershipRequest cuReq = CreateUserA + ndMembershipRequest.newBuilder() + .setUser(createUser) + .build(); + CreateUserAndMembershipResponse cuResp = users. + createUserAndMembership("org_123", cuReq); + System.out.println(cuResp.getUser().getId()); + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/usersCreateUser' + required: true + /api/v1/organizations/{organization_id}/users/{user_id}/permissions: + get: + description: Retrieves all permissions a user has access to within a specific organization. This includes permissions from direct role assignments and inherited permissions from role hierarchy. + tags: + - Users + summary: List user permissions + operationId: UserService_ListUserPermissions + parameters: + - schema: + type: string + description: Unique identifier for the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier for the user + name: user_id + in: path + required: true + responses: + '200': + description: Successfully retrieved the list of permissions for the user + content: + application/json: + schema: + $ref: '#/components/schemas/usersListUserPermissionsResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const { permissions } = await scalekit.user.listUserPermissions("org_123", "usr_123"); + - label: Python SDK + lang: python + source: |- + resp = scalekit_client.users.list_user_permissions( + organization_id="org_123", + user_id="usr_123", + ) + permissions = resp.permissions + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.User().ListUserPermissions(ctx, "org_123", "usr_123") + if err != nil { + // handle error + } + permissions := resp.Permissions + - label: Java SDK + lang: java + source: |- + ListUserPermissionsResponse resp = scalekitClient.users().listUserPermissions("org_123", "usr_123"); + List permissions = resp.getPermissionsList(); + /api/v1/organizations/{organization_id}/users/{user_id}/roles: + get: + description: Retrieves all roles assigned to a user within a specific organization. This includes both direct role assignments and inherited roles from role hierarchy. + tags: + - Users + summary: List user roles + operationId: UserService_ListUserRoles + parameters: + - schema: + type: string + description: Unique identifier for the organization + name: organization_id + in: path + required: true + - schema: + type: string + description: Unique identifier for the user + name: user_id + in: path + required: true + responses: + '200': + description: Successfully retrieved the list of roles assigned to the user + content: + application/json: + schema: + $ref: '#/components/schemas/usersListUserRolesResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const { roles } = await scalekit.user.listUserRoles("org_123", "usr_123"); + - label: Python SDK + lang: python + source: |- + resp = scalekit_client.users.list_user_roles( + organization_id="org_123", + user_id="usr_123", + ) + roles = resp.roles + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.User().ListUserRoles(ctx, "org_123", "usr_123") + if err != nil { + // handle error + } + roles := resp.Roles + - label: Java SDK + lang: java + source: |- + ListUserRolesResponse resp = scalekitClient.users().listUserRoles("org_123", "usr_123"); + List roles = resp.getRolesList(); + /api/v1/organizations/{organization_id}/users:search: + get: + description: Searches for users within a specific organization by email address, user ID, or external ID. The query must be at least 3 characters and is case-insensitive. Scopes results strictly to the given organization. Returns a paginated list of matching users with up to 30 results per page. Use the next_page_token from the response to retrieve subsequent pages. + tags: + - Users + summary: Search organization users + operationId: UserService_SearchOrganizationUsers + parameters: + - schema: + type: string + description: Unique identifier of the organization to search within. Must start with 'org_' and be 1-32 characters long. + name: organization_id + in: path + required: true + - schema: + type: string + minLength: 3 + maxLength: 100 + description: Search term to match against user email, IDs, or external IDs. Must be at least 3 characters. Case insensitive. + name: query + in: query + required: true + - schema: + type: integer + format: int64 + minimum: 1 + maximum: 30 + description: Maximum number of users to return per page. Value must be between 1 and 30. + name: page_size + in: query + - schema: + type: string + description: Token from a previous response for pagination. Provide this to retrieve the next page of results. + name: page_token + in: query + responses: + '200': + description: Matching users within the organization returned; includes pagination cursors for navigating large result sets. + content: + application/json: + schema: + $ref: '#/components/schemas/usersSearchOrganizationUsersResponse' + '400': + description: Bad Request - query must be at least 3 characters and no more than 100 characters, and organization_id must be a valid org_ prefixed identifier. + content: + application/json: + schema: {} + '404': + description: Not Found - organization not found. + content: + application/json: + schema: {} + /api/v1/organizations:external/{external_id}: + get: + description: Retrieves organization details by external ID, including name, region, metadata, and settings. Only provide external_id in the path. If the id query parameter is also supplied, it silently takes precedence over external_id due to protobuf oneof semantics, which causes the request to fail with a 400 Bad Request ('ExternalId is required'). + tags: + - Organizations + summary: Get organization details by external Id + operationId: OrganizationService_GetOrganizationByExternalId + parameters: + - schema: + type: string + description: Unique identifier that links an organization to your app's tenant. Use this with the GetOrganizationByExternalId endpoint. Only one of id or external_id should be provided per request. + name: external_id + in: path + required: true + - schema: + type: string + description: Unique Scalekit-generated identifier for an organization. Use this with the GetOrganization endpoint. Do not pass this parameter when calling GetOrganizationByExternalId — use external_id instead. + name: id + in: query + responses: + '200': + description: Returns the complete organization object with ID, display name, settings, external ID and metadata + content: + application/json: + schema: + $ref: '#/components/schemas/organizationsGetOrganizationResponse' + '400': + description: Invalid request - external ID is empty or the caller's organization claim does not match + content: + application/json: + schema: {} + '404': + description: Organization not found - no organization exists with the specified external ID + content: + application/json: + schema: {} + /api/v1/passwordless/email/resend: + post: + description: Resend a verification email if the user didn't receive it or if the previous code/link has expired + tags: + - Magic link & OTP + summary: Resend passwordless email + operationId: PasswordlessService_ResendPasswordlessEmail + responses: + '200': + description: Successfully resent the passwordless authentication email. Returns updated authentication request details with new expiration time. + content: + application/json: + schema: + $ref: '#/components/schemas/passwordlessSendPasswordlessResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: "const { authRequestId } = sendResponse;\nconst resendResponse = await scalekit.passwordless.resendPasswordlessEmail(\n\n\tauthRequestId\n\n);" + - label: Python SDK + lang: python + source: |- + resend_response = scalekit_client.passwordless.resend_passwordless_email( + auth_request_id=auth_request_id, + ) + + # New auth request ID from resend + new_auth_request_id = resend_response[0].auth_request_id + - label: Go SDK + lang: go + source: |- + resendResponse, err := scalekitClient.Passwordless().ResendPasswordlessEmail( + ctx, + authRequestId, + ) + + if err != nil { + // Handle error + return + } + - label: Java SDK + lang: java + source: SendPasswordlessResponse resendResponse = passwordlessClient.resendPasswordlessEmail(authRequestId); + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/passwordlessResendPasswordlessRequest' + required: true + /api/v1/passwordless/email/send: + post: + description: Send a verification email containing either a verification code (OTP), magic link, or both to a user's email address + tags: + - Magic link & OTP + summary: Send passwordless email + operationId: PasswordlessService_SendPasswordlessEmail + responses: + '200': + description: Successfully sent passwordless authentication email. Returns the authentication request details including expiration time and auth request ID + content: + application/json: + schema: + $ref: '#/components/schemas/passwordlessSendPasswordlessResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: "const response = await scalekit.passwordless.sendPasswordlessEmail(\n\t\"john.doe@example.com\",\n\t{\n\t\ttemplate: \"SIGNIN\",\n\t\texpiresIn: 100,\n\t\tmagiclinkAuthUri: \"https://www.google.com\",\n\t\ttemplateVariables: {\n\t\t\temployeeID: \"EMP523\",\n\t\t\tteamName: \"Alpha Team\",\n\t\t\tsupportEmail: \"support@yourcompany.com\",\n\t\t},\n\t}\n);" + - label: Python SDK + lang: python + source: |- + response = scalekit_client.passwordless.send_passwordless_email( + email="john.doe@example.com", + template="SIGNIN", # or "SIGNUP", "UNSPECIFIED" + expires_in=100, + magiclink_auth_uri="https://www.google.com", + template_variables={ + "employeeID": "EMP523", + "teamName": "Alpha Team", + "supportEmail": "support@yourcompany.com", + }, + ) + + # Extract auth request ID from response + auth_request_id = response[0].auth_request_id + - label: Go SDK + lang: go + source: |- + templateType := scalekit.TemplateTypeSignin + response, err := scalekitClient.Passwordless().SendPasswordlessEmail( + ctx, + "john.doe@example.com", + &scalekit.SendPasswordlessOptions{ + Template: &templateType, + ExpiresIn: 100, + MagiclinkAuthUri: "https://www.google.com", + TemplateVariables: map[string]string{ + "employeeID": "EMP523", + "teamName": "Alpha Team", + "supportEmail": "support@yourcompany.com", + }, + }, + ) + + if err != nil { + // Handle error + return + } + + authRequestId := response.AuthRequestId + - label: Java SDK + lang: java + source: |- + TemplateType templateType = TemplateType.SIGNIN; + Map templateVariables = new HashMap<>(); + templateVariables.put("employeeID", "EMP523"); + templateVariables.put("teamName", "Alpha Team"); + templateVariables.put("supportEmail", "support@yourcompany.com"); + + SendPasswordlessOptions options = new SendPasswordlessOptions(); + options.setTemplate(templateType); + options.setExpiresIn(100); + options.setMagiclinkAuthUri("https://www.example.com"); + options.setTemplateVariables(templateVariables); + + SendPasswordlessResponse response = passwordlessClient.sendPasswordlessEmail( + "john.doe@example.com", + options + ); + + String authRequestId = response.getAuthRequestId(); + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/passwordlessSendPasswordlessRequest' + required: true + /api/v1/passwordless/email/verify: + post: + description: Verify a user's identity using either a verification code or magic link token + tags: + - Magic link & OTP + summary: Verify passwordless email + operationId: PasswordlessService_VerifyPasswordlessEmail + responses: + '200': + description: Successfully verified the passwordless authentication. Returns user email + content: + application/json: + schema: + $ref: '#/components/schemas/passwordlessVerifyPasswordLessResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: "const { authRequestId } = sendResponse;\nconst verifyResponse = await scalekit.passwordless.verifyPasswordlessEmail(\n\n\t// Verification Code (OTP)\n\n\t{ code: \"123456\" },\n\n\t// Magic Link Token\n\n\t{ linkToken: link_token },\n\n\tauthRequestId\n\n);" + - label: Python SDK + lang: python + source: |- + # Verify with OTP code + verify_response = scalekit_client.passwordless.verify_passwordless_email( + code="123456", # OTP code received via email + auth_request_id=auth_request_id, + ) + + # Verify with magic link token + verify_response = scalekit_client.passwordless.verify_passwordless_email( + link_token=link_token, # Magic link token from URL + ) + + # User verified successfully + user_email = verify_response[0].email + - label: Go SDK + lang: go + source: |- + // Verify with OTP code + verifyResponse, err := scalekitClient.Passwordless().VerifyPasswordlessEmail( + ctx, + &scalekit.VerifyPasswordlessOptions{ + Code: "123456", // OTP code + AuthRequestId: authRequestId, + }, + ) + + if err != nil { + // Handle error + return + } + + // Verify with magic link token + verifyResponse, err := scalekitClient.Passwordless().VerifyPasswordlessEmail( + ctx, + &scalekit.VerifyPasswordlessOptions{ + LinkToken: linkToken, // Magic link token + }, + ) + + if err != nil { + // Handle error + return + } + + // User verified successfully + userEmail := verifyResponse.Email + - label: Java SDK + lang: java + source: |- + // Verify with OTP code + VerifyPasswordlessOptions verifyOptions = new VerifyPasswordlessOptions(); + verifyOptions.setCode("123456"); // OTP code + verifyOptions.setAuthRequestId(authRequestId); + + VerifyPasswordLessResponse verifyResponse = passwordlessClient.verifyPasswordlessEmail(verifyOptions); + + // User verified successfully + String userEmail = verifyResponse.getEmail(); + + // Verify with magic link token + VerifyPasswordlessOptions verifyOptions = new VerifyPasswordlessOptions(); + verifyOptions.setLinkToken(linkToken); // Magic link token + + VerifyPasswordLessResponse verifyResponse = passwordlessClient.verifyPasswordlessEmail(verifyOptions); + + // User verified successfully + String userEmail = verifyResponse.getEmail(); + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/passwordlessVerifyPasswordLessRequest' + required: true + /api/v1/permissions: + get: + description: Retrieves a comprehensive, paginated list of all permissions available within the environment. Use this endpoint to view all permission definitions for auditing, role management, or understanding the complete set of available access controls. The response includes pagination tokens to navigate through large sets of permissions efficiently. Each permission object contains the permission name, description, creation time, and last update time. This operation is useful for building permission selection interfaces, auditing permission usage, or understanding the scope of available access controls in your RBAC system. + tags: + - Permissions + summary: List all permissions + operationId: RolesService_ListPermissions + parameters: + - schema: + type: string + description: Page token to retrieve next page of results + name: page_token + in: query + - schema: + type: integer + format: int64 + description: Number of permissions to return per page (max 100) + name: page_size + in: query + - schema: + type: string + enum: + - SCALEKIT + - ENVIRONMENT + description: 'Filter permissions by type: ALL, SCALEKIT, or ENVIRONMENT, where SCALEKIT are predefined Scalekit permissions and ENVIRONMENT are custom permissions created in the environment, default is ALL' + name: type + in: query + responses: + '200': + description: Successfully retrieved the list of permissions. Returns a paginated list of permission objects with metadata and pagination tokens for navigation. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesListPermissionsResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.permission.listPermissions(); + - label: Python SDK + lang: python + source: res = scalekit_client.permissions.list_permissions() + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Permission().ListPermissions(ctx) + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: ListPermissionsResponse res = scalekitClient.permissions().listPermissions(); + post: + description: Creates a new permission that represents a specific action users can perform within the environment. Use this endpoint to define granular access controls for your RBAC system. You can provide a unique permission name following the format 'action:resource' (for example, 'read:documents', 'write:users') and an optional description explaining the permission's purpose. The permission name must be unique across the environment and follows alphanumeric naming conventions with colons and underscores. Returns the created permission object including system-generated ID and timestamps. + tags: + - Permissions + summary: Create new permission + operationId: RolesService_CreatePermission + responses: + '201': + description: Permission created successfully. Returns the complete permission object with system-generated ID, name, description, and timestamps. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesCreatePermissionResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + await scalekit.permission.createPermission({ + name: "read:users", + description: "Allows reading users" + }); + - label: Python SDK + lang: python + source: |- + from scalekit.v1.roles.roles_pb2 import CreatePermission + + permission = CreatePermission( + name="read:users", + description="Allows reading users" + ) + + scalekit_client.permissions.create_permission(permission=permission) + - label: Go SDK + lang: go + source: "resp, err := scalekitClient.Permission().CreatePermission(ctx, &rolesv1.CreatePermission{\n\n\tName: \"read:users\",\n\n\tDescription: \"Allows reading users\",\n\n})\nif err != nil { /* handle err */ }\n_ = resp" + - label: Java SDK + lang: java + source: |- + CreatePermissionResponse res = scalekitClient.permissions().createPermission( + CreatePermissionRequest.newBuilder() + .setPermission( + CreatePermission.newBuilder() + .setName("read:users") + .setDescription("Allows reading users") + .build() + ) + .build() + ); + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/v1rolesCreatePermission' + required: true + /api/v1/permissions/{permission_name}: + get: + description: Retrieves complete information for a specific permission by its unique name identifier. Use this endpoint to view permission details including description, creation time, and last update time. Provide the permission name in the path parameter following the format 'action:resource' (for example, 'read:documents'). This operation is useful for auditing permission definitions, understanding permission purposes, or verifying permission existence before assignment. Returns the complete permission object with all metadata and system-generated timestamps. + tags: + - Permissions + summary: Retrieve permission details + operationId: RolesService_GetPermission + parameters: + - schema: + type: string + description: Name of the permission + name: permission_name + in: path + required: true + responses: + '200': + description: Successfully retrieved permission details. Returns the complete permission object including name, description, creation time, and update time. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesGetPermissionResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.permission.getPermission("read:users"); + - label: Python SDK + lang: python + source: |- + res = scalekit_client.permissions.get_permission( + permission_name="read:users" + ) + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Permission().GetPermission(ctx, "read:users") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: GetPermissionResponse res = scalekitClient.permissions().getPermission("read:users"); + put: + description: Modifies an existing permission's attributes including description and metadata. Use this endpoint to update permission descriptions or clarify permission purposes after creation. The permission is identified by its unique name in the path parameter, and only the fields you specify in the request body will be updated. Note that the permission name itself cannot be changed as it serves as the immutable identifier. This operation is useful for maintaining clear documentation of permission purposes or updating descriptions to reflect changes in system functionality. Returns the updated permission object with modified timestamps. + tags: + - Permissions + summary: Update permission details + operationId: RolesService_UpdatePermission + parameters: + - schema: + type: string + description: Name of the permission + name: permission_name + in: path + required: true + responses: + '200': + description: Permission updated successfully. Returns the modified permission object with updated description and timestamps. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesUpdatePermissionResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + await scalekit.permission.updatePermission("read:users", { + name: "read:users", + description: "Allows reading user resources" + }); + - label: Python SDK + lang: python + source: |- + from scalekit.v1.roles.roles_pb2 import CreatePermission + + scalekit_client.permissions.update_permission( + permission_name="read:users", + permission=CreatePermission( + name="read:users", + description="Allows reading user resources" + ) + ) + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Permission().UpdatePermission(ctx, "read:users", &rolesv1.CreatePermission{ + Name: "read:users", + Description: "Allows reading user resources", + }) + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: |- + UpdatePermissionResponse res = scalekitClient.permissions().updatePermission( + "read:users", + UpdatePermissionRequest.newBuilder() + .setPermission( + CreatePermission.newBuilder() + .setName("read:users") + .setDescription("Allows reading user resources") + .build() + ) + .build() + ); + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/v1rolesCreatePermission' + required: true + delete: + description: Permanently removes a permission from the environment using its unique name identifier. Use this endpoint when you need to clean up unused permissions or remove access controls that are no longer relevant. The permission is identified by its name in the path parameter following the format 'action:resource'. This operation cannot be undone, so ensure no active roles depend on the permission before deletion. If the permission is currently assigned to any roles, you may need to remove those assignments first or update the roles to use alternative permissions. Returns no content on successful deletion. + tags: + - Permissions + summary: Delete permission + operationId: RolesService_DeletePermission + parameters: + - schema: + type: string + description: Name of the permission + name: permission_name + in: path + required: true + responses: + '200': + description: Permission successfully deleted. No content returned. + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: await scalekit.permission.deletePermission("read:users"); + - label: Python SDK + lang: python + source: |- + scalekit_client.permissions.delete_permission( + permission_name="read:users" + ) + - label: Go SDK + lang: go + source: |- + err := scalekitClient.Permission().DeletePermission(ctx, "read:users") + if err != nil { /* handle err */ } + - label: Java SDK + lang: java + source: scalekitClient.permissions().deletePermission("read:users"); + /api/v1/roles: + get: + description: Retrieves a comprehensive list of all roles available within the specified environment including organization roles. Use this endpoint to view all role definitions, including custom roles and their configurations. You can optionally include permission details for each role to understand their capabilities. This is useful for role management, auditing organization access controls, or understanding the available access levels within the organization. + tags: + - Roles + summary: List all roles in environment + operationId: RolesService_ListRoles + parameters: + - schema: + type: string + description: 'Include additional data in the response. Valid values: ''permissions'' (direct permissions only), ''permissions:all'' (includes inherited permissions from role hierarchy)' + name: include + in: query + responses: + '200': + description: Successfully retrieved list of roles. Returns all roles with their metadata and optionally their permissions. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesListRolesResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.role.listRoles(); + - label: Python SDK + lang: python + source: res = scalekit_client.roles.list_roles() + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Role().ListRoles(ctx) + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: ListRolesResponse res = scalekitClient.roles().listRoles(); + post: + description: Creates a new role within the environment with specified permissions and metadata. Use this endpoint to define custom roles that can be assigned to users or groups. You can create hierarchical roles by extending existing roles, assign specific permissions, and configure display information. Roles are the foundation of your access control system and determine what actions users can perform. + tags: + - Roles + summary: Create new role in environment + operationId: RolesService_CreateRole + responses: + '201': + description: Role created successfully. Returns the complete role object with system-generated ID and timestamps. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesCreateRoleResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + await scalekit.role.createRole({ + name: "admin", + displayName: "Admin", + description: "Environment-level role", + extends: "base_role", // optional + permissions: ["read:users"] // optional + }); + - label: Python SDK + lang: python + source: |- + from scalekit.v1.roles.roles_pb2 import CreateRole + + role = CreateRole( + name="admin", + display_name="Admin", + description="Environment-level role", + extends="base_role", # optional + permissions=["read:users"] # optional + ) + + scalekit_client.roles.create_role(role=role) + - label: Go SDK + lang: go + source: "resp, err := scalekitClient.Role().CreateRole(ctx, &rolesv1.CreateRole{\n\n\tName: \"admin\",\n\n\tDisplayName: \"Admin\",\n\n\tDescription: \"Environment-level role\",\n\n\tExtends: proto.String(\"base_role\"), // optional\n\n\tPermissions: []string{\"read:users\"}, // optional\n\n})" + - label: Java SDK + lang: java + source: |- + CreateRoleResponse res = scalekitClient.roles().createRole( + CreateRoleRequest.newBuilder() + .setRole( + CreateRole.newBuilder() + .setName("admin") + .setDisplayName("Admin") + .setDescription("Environment-level role") + // .setExtends("base_role") // optional + // .addPermissions("read:users") // optional + .build() + ) + .build() + ); + requestBody: + content: + application/json: + schema: + description: Role configuration details including name, display name, description, permissions, and inheritance settings. + $ref: '#/components/schemas/v1rolesCreateRole' + examples: + - description: Can edit content + display_name: Content Editor + name: content_editor + permissions: + - read:content + - write:content + required: true + /api/v1/roles/default: + patch: + description: Updates the default creator and member roles for the current environment. Use this endpoint to configure which roles are automatically assigned to new users when they join the environment. You can specify role names for both creator and member default roles. The system will validate that the specified roles exist and update the environment settings accordingly. Returns the updated default role objects including their complete role information and permissions. + tags: + - Roles + summary: Set default creator and member roles + operationId: RolesService_UpdateDefaultRoles2 + responses: + '200': + description: Default roles updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/rolesUpdateDefaultRolesResponse' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/rolesUpdateDefaultRolesRequest' + required: true + /api/v1/roles/{role_name}: + get: + description: Retrieves complete information for a specific role including metadata and inheritance details (base role and dependent role count). Use this endpoint to audit role configuration and understand the role's place in the hierarchy. To view the role's permissions, use the ListRolePermissions endpoint. + tags: + - Roles + summary: Get role details + operationId: RolesService_GetRole + parameters: + - schema: + type: string + description: Unique name identifier of the role to retrieve. Must be alphanumeric with underscores, 1-64 characters. + name: role_name + in: path + required: true + - schema: + type: string + description: 'Include additional data in the response. Valid values: ''permissions'' (direct permissions only), ''permissions:all'' (includes inherited permissions from role hierarchy)' + name: include + in: query + responses: + '200': + description: Successfully retrieved role details. Returns the role object including metadata and inheritance details. Permissions are not included. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesGetRoleResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.role.getRole("admin"); + - label: Python SDK + lang: python + source: res = scalekit_client.roles.get_role(role_name="admin") + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Role().GetRole(ctx, "admin") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: GetRoleResponse res = scalekitClient.roles().getRole("admin"); + put: + description: Modifies an existing role's properties including display name, description, permissions, and inheritance. Use this endpoint to update role metadata, change permission assignments, or modify role hierarchy. Only the fields you specify will be updated, leaving other properties unchanged. When updating permissions, the new list replaces all existing permissions for the role. + tags: + - Roles + summary: Update role information + operationId: RolesService_UpdateRole + parameters: + - schema: + type: string + description: Unique name identifier of the role to update. Must be alphanumeric with underscores, 1-64 characters. + name: role_name + in: path + required: true + responses: + '200': + description: Role updated successfully. Returns the modified role object with updated timestamps. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesUpdateRoleResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + await scalekit.role.updateRole("admin", { + displayName: "Admin (Updated)", + description: "Updated description" + }); + - label: Python SDK + lang: python + source: |- + from scalekit.v1.roles.roles_pb2 import UpdateRole + + scalekit_client.roles.update_role( + role_name="admin", + role=UpdateRole( + display_name="Admin (Updated)", + description="Updated description" + ) + ) + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Role().UpdateRole(ctx, "admin", &rolesv1.UpdateRole{ + DisplayName: "Admin (Updated)", + Description: "Updated description", + }) + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: |- + UpdateRoleResponse res = scalekitClient.roles().updateRole( + "admin", + UpdateRoleRequest.newBuilder() + .setRole( + UpdateRole.newBuilder() + .setDisplayName("Admin (Updated)") + .setDescription("Updated description") + .build() + ) + .build() + ); + requestBody: + content: + application/json: + schema: + description: Role fields to update. Only specified fields will be modified. + $ref: '#/components/schemas/v1rolesUpdateRole' + examples: + - description: Can edit and approve content + display_name: Senior Editor + required: true + delete: + description: Permanently removes a role from the environment and reassigns users who had that role to a different role. Use this endpoint when you need to clean up unused roles or restructure your access control system. The role cannot be deleted if it has dependent roles (roles that extend it) unless you specify a replacement role. If users are assigned to the role being deleted, you must provide a reassign_role_name to move those users to a different role before deletion can proceed. This action cannot be undone, so ensure no critical users depend on the role before deletion. + tags: + - Roles + summary: Delete role and reassign users + operationId: RolesService_DeleteRole + parameters: + - schema: + type: string + description: Unique name identifier of the role to delete. Must be alphanumeric with underscores, 1-64 characters. + name: role_name + in: path + required: true + - schema: + type: string + description: Role name to reassign users to when deleting this role + name: reassign_role_id + in: query + - schema: + type: string + description: Role name to reassign users to when deleting this role + name: reassign_role_name + in: query + responses: + '200': + description: Role successfully deleted and users reassigned. No content returned. + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + // Basic delete + await scalekit.role.deleteRole("admin"); + + // With reassignment + await scalekit.role.deleteRole("admin", "member"); + - label: Python SDK + lang: python + source: |- + # Basic delete + scalekit_client.roles.delete_role(role_name="admin") + + # With reassignment + scalekit_client.roles.delete_role( + role_name="admin", + reassign_role_name="member" + ) + - label: Go SDK + lang: go + source: |- + // Basic delete + err := scalekitClient.Role().DeleteRole(ctx, "admin") + if err != nil { /* handle err */ } + + // With reassignment + err = scalekitClient.Role().DeleteRole(ctx, "admin", "member") + - label: Java SDK + lang: java + source: |- + // Basic delete + scalekitClient.roles().deleteRole("admin"); + + // With reassignment + scalekitClient.roles().deleteRole("admin", "member"); + /api/v1/roles/{role_name}/dependents: + get: + description: Retrieves all roles that directly extend the specified base role through inheritance. Use this endpoint to understand the role hierarchy and identify which roles inherit permissions from a particular base role. Provide the base role name as a path parameter, and the response will include all dependent roles with their metadata and permission information. This operation is useful for auditing role inheritance relationships, understanding the impact of changes to base roles, or managing role hierarchies effectively. Returns a list of dependent role objects including their names, display names, descriptions, and permission details. + tags: + - Roles + summary: List dependent roles + operationId: RolesService_ListDependentRoles + parameters: + - schema: + type: string + description: Name of the base role + name: role_name + in: path + required: true + responses: + '200': + description: Successfully retrieved dependent roles. Returns a list of all roles that extend the specified base role, including their metadata and permission information. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesListDependentRolesResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.role.listDependentRoles("admin"); + - label: Python SDK + lang: python + source: res = scalekit_client.roles.list_dependent_roles(role_name="admin") + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Role().ListDependentRoles(ctx, "admin") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: ListDependentRolesResponse res = scalekitClient.roles().listDependentRoles("admin"); + /api/v1/roles/{role_name}/permissions: + get: + description: Retrieves all permissions directly assigned to the specified role, excluding permissions inherited from base roles. Use this endpoint to view the explicit permission assignments for a role, which is useful for understanding direct role capabilities, auditing permission assignments, or managing role-permission relationships. Provide the role name as a path parameter, and the response will include only the permissions that are directly assigned to that role. This operation does not include inherited permissions from role hierarchies - use ListEffectiveRolePermissions to see the complete set of permissions including inheritance. Returns a list of permission objects with their names, descriptions, and assignment metadata. + tags: + - Roles + summary: List permissions for role + operationId: RolesService_ListRolePermissions + parameters: + - schema: + type: string + description: Name of the role + name: role_name + in: path + required: true + responses: + '200': + description: Successfully retrieved role permissions. Returns a list of all permissions directly assigned to the specified role, excluding inherited permissions. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesListRolePermissionsResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.permission.listRolePermissions("admin"); + - label: Python SDK + lang: python + source: res = scalekit_client.permissions.list_role_permissions(role_name="admin") + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Permission().ListRolePermissions(ctx, "admin") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: ListRolePermissionsResponse res = scalekitClient.permissions().listRolePermissions("admin"); + post: + description: Adds one or more permissions to the specified role while preserving existing permission assignments. Use this endpoint to grant additional capabilities to a role without affecting its current permission set. Provide the role name as a path parameter and a list of permission names in the request body. The system will validate that all specified permissions exist in the environment and add them to the role. Existing permission assignments remain unchanged, making this operation safe for incremental permission management. This is useful for gradually expanding role capabilities or adding new permissions as your system evolves. Returns the updated list of all permissions now assigned to the role. + tags: + - Roles + summary: Add permissions to role + operationId: RolesService_AddPermissionsToRole + parameters: + - schema: + type: string + description: Name of the role + name: role_name + in: path + required: true + responses: + '200': + description: Permissions added to role successfully. Returns the complete list of all permissions now assigned to the role, including both existing and newly added permissions. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesAddPermissionsToRoleResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: await scalekit.permission.addPermissionsToRole("role_admin", ["perm.read", "perm.write"]); + - label: Python SDK + lang: python + source: |- + scalekit_client.permissions.add_permissions_to_role( + role_name="role_admin", + permission_names=["perm.read", "perm.write"] + ) + - label: Go SDK + lang: go + source: resp, err := scalekitClient.Permission().AddPermissionsToRole(ctx, "role_admin", []string{"perm.read", "perm.write"}) + - label: Java SDK + lang: java + source: |- + AddPermissionsToRoleResponse res = scalekitClient.permissions().addPermissionsToRole( + "role_admin", + AddPermissionsToRoleRequest.newBuilder() + .addPermissionNames("perm.read") + .addPermissionNames("perm.write") + .build() + ); + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RolesServiceAddPermissionsToRoleBody' + required: true + /api/v1/roles/{role_name}/permissions/{permission_name}: + delete: + description: Removes a specific permission from the specified role, revoking that capability from all users assigned to the role. Use this endpoint to restrict role capabilities or remove unnecessary permissions. Provide both the role name and permission name as path parameters. This operation only affects the direct permission assignment and does not impact permissions inherited from base roles. If the permission is inherited through role hierarchy, you may need to modify the base role instead. This is useful for fine-tuning role permissions, implementing least-privilege access controls, or removing deprecated permissions. Returns no content on successful removal. + tags: + - Roles + summary: Remove permission from role + operationId: RolesService_RemovePermissionFromRole + parameters: + - schema: + type: string + description: Name of the role + name: role_name + in: path + required: true + - schema: + type: string + description: Name of the permission to remove + name: permission_name + in: path + required: true + responses: + '200': + description: Permission removed from role successfully. No content returned. + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: await scalekit.permission.removePermissionFromRole("admin", "read:users"); + - label: Python SDK + lang: python + source: |- + scalekit_client.permissions.remove_permission_from_role( + role_name="admin", + permission_name="read:users" + ) + - label: Go SDK + lang: go + source: |- + err := scalekitClient.Permission().RemovePermissionFromRole(ctx, "admin", "read:users") + if err != nil { /* handle err */ } + - label: Java SDK + lang: java + source: scalekitClient.permissions().removePermissionFromRole("admin", "read:users"); + /api/v1/roles/{role_name}/permissions:all: + get: + description: Retrieves the complete set of effective permissions for a role, including both directly assigned permissions and permissions inherited from base roles through the role hierarchy. Use this endpoint to understand the full scope of capabilities available to users assigned to a specific role. Provide the role name as a path parameter, and the response will include all permissions that apply to the role, accounting for inheritance relationships. This operation is essential for auditing role capabilities, understanding permission inheritance, or verifying the complete access scope before role assignment. Returns a comprehensive list of permission names representing the full set of effective permissions for the specified role. + tags: + - Roles + summary: List effective permissions for role + operationId: RolesService_ListEffectiveRolePermissions + parameters: + - schema: + type: string + description: Name of the role + name: role_name + in: path + required: true + responses: + '200': + description: Successfully retrieved effective permissions. Returns the complete list of all permissions that apply to the role, including both direct assignments and inherited permissions from base roles. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesListEffectiveRolePermissionsResponse' + /api/v1/roles/{role_name}/users:count: + get: + description: Retrieves the total number of users currently assigned to the specified role within the environment. Use this endpoint to monitor role usage, enforce user limits, or understand the scope of role assignments. Provide the role's unique name as a path parameter, and the response will include the current user count for that role. This operation is read-only and does not modify any data or user assignments. The count reflects all users who have the role either directly assigned or inherited through organization membership. This information is useful for capacity planning, security auditing, or understanding the impact of role changes across your user base. + tags: + - Roles + summary: Retrieve user count for role + operationId: RolesService_GetRoleUsersCount + parameters: + - schema: + type: string + description: Unique name of the role + name: role_name + in: path + required: true + responses: + '200': + description: Successfully retrieved user count for the specified role. Returns the total number of users currently assigned to the role, including both direct assignments and inherited assignments. + content: + application/json: + schema: + $ref: '#/components/schemas/rolesGetRoleUsersCountResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.role.getRoleUsersCount("admin"); + - label: Python SDK + lang: python + source: res = scalekit_client.roles.get_role_users_count(role_name="admin") + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Role().GetRoleUsersCount(ctx, "admin") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: GetRoleUsersCountResponse res = scalekitClient.roles().getRoleUsersCount("admin"); + /api/v1/roles:set_defaults: + patch: + description: Updates the default creator and member roles for the current environment. Use this endpoint to configure which roles are automatically assigned to new users when they join the environment. You can specify role names for both creator and member default roles. The system will validate that the specified roles exist and update the environment settings accordingly. Returns the updated default role objects including their complete role information and permissions. + tags: + - Roles + summary: Set default creator and member roles + operationId: RolesService_UpdateDefaultRoles + responses: + '200': + description: Default roles updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/rolesUpdateDefaultRolesResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + const res = await scalekit.role.updateDefaultRoles({ + defaultMemberRole: "member" + }); + - label: Python SDK + lang: python + source: |- + from scalekit.v1.roles.roles_pb2 import UpdateDefaultRolesRequest + + res = scalekit_client.roles.update_default_roles( + default_roles=UpdateDefaultRolesRequest( + default_member_role="member" + ) + ) + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Role().UpdateDefaultRoles(ctx, "member") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: |- + UpdateDefaultRolesResponse res = scalekitClient.roles().updateDefaultRoles( + UpdateDefaultRolesRequest.newBuilder() + .setDefaultMemberRole("member") + .build() + ); + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/rolesUpdateDefaultRolesRequest' + required: true + /api/v1/sessions/{session_id}: + get: + description: Retrieves comprehensive details for a specific user session including authentication status, device information, and expiration timelines. Use this endpoint to fetch current session metadata for security audits, session validation, or to display session information in user account management interfaces. Returns all session properties including the user ID, authenticated organizations, device details with browser/OS information, IP address and geolocation, and all relevant timestamps (creation, last activity, idle expiration, absolute expiration, and actual expiration if applicable). + tags: + - Sessions + summary: Get session details + operationId: SessionService_GetSession + parameters: + - schema: + type: string + description: Unique identifier for the session. Must start with 'ses_' prefix. + name: session_id + in: path + required: true + responses: + '200': + description: Successfully retrieved session details + content: + application/json: + schema: + $ref: '#/components/schemas/sessionsSessionDetails' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.session.getSession("ses_123456789"); + - label: Python SDK + lang: python + source: res = scalekit_client.sessions.get_session(session_id="ses_123456789") + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Session().GetSession(ctx, "ses_123456789") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: SessionDetails res = scalekitClient.sessions().getSession("ses_123456789"); + /api/v1/sessions/{session_id}/revoke: + post: + description: Immediately invalidates a specific user session by session ID, setting its status to 'revoked'. Once revoked, the session cannot be used for any future API requests or application access. Use this endpoint to implement session-level logout, force a user to reauthenticate on a specific device, or terminate suspicious sessions. The revocation is instantaneous and irreversible. Returns the revoked session details including the session ID, user ID, and the revocation timestamp. + tags: + - Sessions + summary: Revoke user session + operationId: SessionService_RevokeSession + parameters: + - schema: + type: string + description: Unique identifier for the session to revoke. Must start with 'ses_' prefix. + name: session_id + in: path + required: true + responses: + '200': + description: Successfully revoked the session. Returns the revoked session details + content: + application/json: + schema: + $ref: '#/components/schemas/sessionsRevokeSessionResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.session.revokeSession("ses_123456789"); + - label: Python SDK + lang: python + source: res = scalekit_client.sessions.revoke_session(session_id="ses_123456789") + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Session().RevokeSession(ctx, "ses_123456789") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: RevokeSessionResponse res = scalekitClient.sessions().revokeSession("ses_123456789"); + /api/v1/users: + get: + description: Retrieves a paginated list of all users across your entire environment. Use this endpoint to view all users regardless of their organization memberships. This is useful for administrative purposes, user audits, or when you need to see all users in your Scalekit environment. Supports pagination for large user bases. + tags: + - Users + summary: List all users in environment + operationId: UserService_ListUsers + parameters: + - schema: + type: integer + format: int64 + description: Maximum number of organizations to return per page. Must be between 10 and 100 + name: page_size + in: query + - schema: + type: string + description: Pagination token from the previous response. Use to retrieve the next page of organizations + name: page_token + in: query + responses: + '200': + description: List of users. + content: + application/json: + schema: + $ref: '#/components/schemas/usersListUsersResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + const response = await scalekit.user.listUsers( + { pageSize: 100 }); + - label: Python SDK + lang: python + source: |- + # pass empty org to fetch all users in environment + resp,_ = scalekit_client.users.list_users(organization_id="", page_size=100) + - label: Go SDK + lang: go + source: 'all, err := scalekitClient.User().ListUsers(ctx, &scalekit.ListUsersOptions{PageSize: 100})' + - label: Java SDK + lang: java + source: |- + ListUsersRequest lur = ListUsersRequest. + newBuilder().setPageSize(100).build(); + ListUsersResponse allUsers = users.listUsers(lur); + /api/v1/users/{id}: + get: + description: Retrieves all details for a user by system-generated user ID or external ID. The response includes organization memberships and user metadata. + tags: + - Users + summary: Get user + operationId: UserService_GetUser + parameters: + - schema: + type: string + description: System-generated user ID + name: id + in: path + required: true + - schema: + type: string + description: Your application's unique identifier for this organization, used to link Scalekit with your system. + name: external_id + in: query + responses: + '200': + description: User details retrieved successfully. Returns full user object with system-generated fields and timestamps. + content: + application/json: + schema: + $ref: '#/components/schemas/usersGetUserResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const { user } = await scalekit.user.getUser("usr_123456"); + - label: Python SDK + lang: python + source: |- + resp = scalekit_client.users.get_user(user_id="usr_123456") + user = resp.user + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.User().GetUser(ctx, "usr_123456") + if err != nil { + // handle error + } + user := resp.User + - label: Java SDK + lang: java + source: |- + GetUserResponse resp = scalekitClient.users().getUser("usr_123456"); + User user = resp.getUser(); + delete: + description: Permanently removes a user from your environment and deletes all associated data. Use this endpoint when you need to completely remove a user account. This action deletes the user's profile, memberships, and all related data across all organizations. This operation cannot be undone, so use with caution. + tags: + - Users + summary: Delete user permanently + operationId: UserService_DeleteUser + parameters: + - schema: + type: string + description: System-generated user ID. Must start with 'usr_' (19-25 characters) + name: id + in: path + required: true + - schema: + type: string + description: External system identifier from connected directories. Must match existing records + name: external_id + in: query + responses: + '200': + description: User successfully deleted. No content returned + content: + application/json: + schema: {} + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: await scalekit.user.deleteUser("usr_123"); + - label: Python SDK + lang: python + source: |- + scalekit_client.users.delete_user(organization_id="org_123", + user_id="usr_123") + - label: Go SDK + lang: go + source: |- + if err := scalekitClient.User().DeleteUser(ctx, + "usr_123"); err != nil { + panic(err) + } + - label: Java SDK + lang: java + source: users.deleteUser("usr_123"); + patch: + description: Modifies user account information including profile details, metadata, and external ID. Use this endpoint to update a user's personal information, contact details, or custom metadata. You can update the user's profile, phone number, and metadata fields. Note that fields like user ID, email address, environment ID, and creation time cannot be modified. + tags: + - Users + summary: Update user information + operationId: UserService_UpdateUser + parameters: + - schema: + type: string + description: System-generated user ID. Must start with 'usr_' and be 19-25 characters long. + name: id + in: path + required: true + - schema: + type: string + description: Your application's unique identifier for this organization, used to link Scalekit with your system. + name: external_id + in: query + responses: + '200': + description: User updated successfully. Returns the modified user object with updated timestamps. + content: + application/json: + schema: + $ref: '#/components/schemas/usersUpdateUserResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: "await scalekit.user.updateUser(\"usr_123\", {\n\tuserProfile: {\n\t\tfirstName: \"John\",\n\t\tlastName: \"Smith\",\n\t},\n\tmetadata: {\n\t\tdepartment: \"sales\",\n\t},\n});" + - label: Python SDK + lang: python + source: |- + import os + from scalekit import ScalekitClient + from scalekit.v1.users.users_pb2 import UpdateUser + from scalekit.v1.commons.commons_pb2 import UserProfile + scalekit_client = ScalekitClient( + env_url=os.getenv("SCALEKIT_ENV_URL"), + client_id=os.getenv("SCALEKIT_CLIENT_ID"), + client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), + ) + update_user = UpdateUser( + user_profile=UserProfile( + first_name="John", + last_name="Smith" + ), + metadata={"department": "sales"} + ) + scalekit_client.users.update_user(organization_id="org_123", + user=update_user) + - label: Go SDK + lang: go + source: |- + upd := &usersv1.UpdateUser{ + UserProfile: &usersv1.UpdateUserProfile{ + FirstName: "John", + LastName: "Smith", + }, + Metadata: map[string]string{ + "department": "sales", + }, + } + scalekitClient.User().UpdateUser(ctx, "usr_123", upd) + - label: Java SDK + lang: java + source: |- + UpdateUser upd = UpdateUser.newBuilder() + .setUserProfile( + UpdateUserProfile.newBuilder() + .setFirstName("John") + .setLastName("Smith") + .build()) + .putMetadata("department", "sales") + .build(); + UpdateUserRequest updReq = UpdateUserRequest. + newBuilder().setUser(upd).build(); + users.updateUser("usr_123", updReq); + requestBody: + content: + application/json: + schema: + description: User fields to update. Only specified fields will be modified. Required fields must be provided if being changed. + $ref: '#/components/schemas/v1usersUpdateUser' + examples: + - firstName: John + lastName: Doe + required: true + /api/v1/users/{user_id}/sessions: + get: + description: Retrieves a paginated list of all sessions associated with a specific user across all devices and browsers. Use this endpoint to audit user activity, display all active sessions in account management interfaces, or verify user authentication status across devices. Supports filtering by session status (active, expired, revoked, logout) and time range (creation date). Returns session details for each session including device information, IP address, geolocation, and current status. The response includes pagination metadata (page tokens and total count) to handle large session lists efficiently. + tags: + - Sessions + summary: List user sessions + operationId: SessionService_GetUserSessions + parameters: + - schema: + type: string + description: Unique identifier for the user whose sessions to retrieve. Must start with 'usr_' prefix. + name: user_id + in: path + required: true + - schema: + type: integer + format: int64 + description: Maximum number of sessions to return in a single page. Optional parameter. If not specified, defaults to a server-defined limit. Use smaller values for faster responses, larger values for fewer requests. + name: page_size + in: query + - schema: + type: string + description: Pagination token from the previous response for retrieving the next page of results. Leave empty for the first page. Use the next_page_token from a previous response to fetch subsequent pages. + name: page_token + in: query + - schema: + type: array + items: + type: string + style: form + explode: true + description: 'Filter sessions by one or more status values. Possible values: ''active'', ''expired'', ''revoked'', ''logout''. Leave empty to include all statuses. Multiple values use OR logic (e.g., status=[''active'', ''expired''] returns sessions that are either active OR expired).' + name: filter.status + in: query + - schema: + type: string + format: date-time + description: Filter to include only sessions created on or after this timestamp. Optional. Uses RFC 3339 format. Useful for querying sessions within a specific time window. + name: filter.start_time + in: query + - schema: + type: string + format: date-time + description: Filter to include only sessions created on or before this timestamp. Optional. Uses RFC 3339 format. Must be after start_time if both are specified. + name: filter.end_time + in: query + responses: + '200': + description: Successfully retrieved user sessions. Returns a list of sessions with pagination information + content: + application/json: + schema: + $ref: '#/components/schemas/sessionsUserSessionDetails' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + // Basic usage + const res = await scalekit.session.getUserSessions("user_123"); + + // With pagination and filtering + const res = await scalekit.session.getUserSessions("user_123", { + pageSize: 10, + pageToken: "next_page_token", + filter: { + status: ["ACTIVE"], + startTime: new Date("2024-01-01"), + endTime: new Date("2024-12-31") + } + }); + - label: Python SDK + lang: python + source: |- + # Basic usage + res = scalekit_client.sessions.get_user_sessions(user_id="user_123") + + # With pagination and filtering + from google.protobuf.timestamp_pb2 import Timestamp + from datetime import datetime + + start_time = Timestamp() + start_time.FromDatetime(datetime(2024, 1, 1)) + end_time = Timestamp() + end_time.FromDatetime(datetime(2024, 12, 31)) + + filter_obj = scalekit_client.sessions.create_session_filter( + status=["ACTIVE"], start_time=start_time, end_time=end_time + ) + res = scalekit_client.sessions.get_user_sessions( + user_id="user_123", page_size=10, page_token="next_page_token", filter=filter_obj + ) + - label: Go SDK + lang: go + source: |- + // Basic usage + resp, err := scalekitClient.Session().GetUserSessions(ctx, "user_123", 0, "", nil) + if err != nil { /* handle err */ } + + // With pagination and filtering + // import "time", sessionsv1 "...", "google.golang.org/protobuf/types/known/timestamppb" + startTime, _ := time.Parse(time.RFC3339, "2024-01-01T00:00:00Z") + endTime, _ := time.Parse(time.RFC3339, "2024-12-31T23:59:59Z") + filter := &sessionsv1.UserSessionFilter{ + Status: []string{"ACTIVE"}, + StartTime: timestamppb.New(startTime), + EndTime: timestamppb.New(endTime), + } + resp, err := scalekitClient.Session().GetUserSessions(ctx, "user_123", 10, "next_page_token", filter) + if err != nil { /* handle err */ } + - label: Java SDK + lang: java + source: |- + // Basic usage + UserSessionDetails res = scalekitClient.sessions().getUserSessions("user_123", null, null, null); + + // With pagination and filtering + // import UserSessionFilter, Timestamp, Instant + UserSessionFilter filter = UserSessionFilter.newBuilder() + .addStatus("ACTIVE") + .setStartTime(Timestamp.newBuilder().setSeconds(Instant.parse("2024-01-01T00:00:00Z").getEpochSecond()).build()) + .setEndTime(Timestamp.newBuilder().setSeconds(Instant.parse("2024-12-31T23:59:59Z").getEpochSecond()).build()) + .build(); + UserSessionDetails res = scalekitClient.sessions().getUserSessions("user_123", 10, "next_page_token", filter); + /api/v1/users/{user_id}/sessions/revoke: + post: + description: Immediately invalidates all active sessions for a specific user across all devices and browsers, setting their status to 'revoked'. Use this endpoint to implement global logout functionality, force re-authentication after security incidents, or terminate all sessions following a password reset or credential compromise. Only active sessions are revoked; already expired, logout, or previously revoked sessions remain unchanged. The revocation is atomic and instantaneous. Returns a list of all revoked sessions with their details and a total count of sessions revoked. + tags: + - Sessions + summary: Revoke all user sessions + operationId: SessionService_RevokeAllUserSessions + parameters: + - schema: + type: string + description: Unique identifier for the user whose all sessions will be revoked. Must start with 'usr_' prefix. + name: user_id + in: path + required: true + responses: + '200': + description: Successfully revoked all user sessions. Returns the list of revoked sessions and total count + content: + application/json: + schema: + $ref: '#/components/schemas/sessionsRevokeAllUserSessionsResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.session.revokeAllUserSessions("user_123"); + - label: Python SDK + lang: python + source: res = scalekit_client.sessions.revoke_all_user_sessions(user_id="user_123") + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.Session().RevokeAllUserSessions(ctx, "user_123") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: RevokeAllUserSessionsResponse res = scalekitClient.sessions().revokeAllUserSessions("user_123"); + /api/v1/users:search: + get: + description: Searches for users across the entire environment by email address, user ID, or external ID. The query must be at least 3 characters and is case-insensitive. Returns a paginated list of matching users with up to 30 results per page. Use the next_page_token from the response to retrieve subsequent pages. + tags: + - Users + summary: Search users + operationId: UserService_SearchUsers + parameters: + - schema: + type: string + minLength: 3 + maxLength: 100 + description: Search term to match against user email, IDs, or external IDs. Must be at least 3 characters. Case insensitive. + name: query + in: query + required: true + - schema: + type: integer + format: int64 + minimum: 1 + maximum: 30 + description: Maximum number of users to return per page. Value must be between 1 and 30. + name: page_size + in: query + - schema: + type: string + description: Token from a previous response for pagination. Provide this to retrieve the next page of results. + name: page_token + in: query + responses: + '200': + description: Matching users returned; includes pagination cursors for navigating large result sets. + content: + application/json: + schema: + $ref: '#/components/schemas/usersSearchUsersResponse' + '400': + description: Bad Request - query must be at least 3 characters and no more than 100 characters. + content: + application/json: + schema: {} + /api/v1/webauthn/credentials: + get: + description: Retrieves all registered passkeys for the current user, including device information, creation timestamps, and display names. Use this to show users their registered authenticators. + tags: + - Passkeys + summary: List user's passkeys + operationId: WebAuthnService_ListCredentials + parameters: + - schema: + type: string + description: User ID to list credentials for (optional, current user if not provided) + name: user_id + in: query + responses: + '200': + description: List of passkeys with metadata + content: + application/json: + schema: + $ref: '#/components/schemas/webauthnListCredentialsResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.webauthn.listCredentials("user_123"); + - label: Python SDK + lang: python + source: res = scalekit_client.webauthn.list_credentials(user_id="user_123") + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.WebAuthn().ListCredentials(ctx, "user_123") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: ListCredentialsResponse res = scalekitClient.webauthn().listCredentials("user_123"); + /api/v1/webauthn/credentials/{credential_id}: + delete: + description: Deletes a specific passkey credential for the current user. After removal, the authenticator can no longer be used for authentication. + tags: + - Passkeys + summary: Remove a passkey + operationId: WebAuthnService_DeleteCredential + parameters: + - schema: + type: string + description: The credential ID to delete + name: credential_id + in: path + required: true + responses: + '200': + description: Passkey successfully deleted + content: + application/json: + schema: + $ref: '#/components/schemas/webauthnDeleteCredentialResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: const res = await scalekit.webauthn.deleteCredential("wac_123"); + - label: Python SDK + lang: python + source: res = scalekit_client.webauthn.delete_credential(credential_id="wac_123") + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.WebAuthn().DeleteCredential(ctx, "wac_123") + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: DeleteCredentialResponse res = scalekitClient.webauthn().deleteCredential("wac_123"); + patch: + description: Updates the display name of a passkey credential to help users identify their authenticators. Only the display name can be modified. + tags: + - Passkeys + summary: Rename a passkey + operationId: WebAuthnService_UpdateCredential + parameters: + - schema: + type: string + description: The credential ID to update + name: credential_id + in: path + required: true + responses: + '200': + description: Passkey successfully updated with new name + content: + application/json: + schema: + $ref: '#/components/schemas/webauthnUpdateCredentialResponse' + x-codeSamples: + - label: Node.js SDK + lang: javascript + source: |- + const res = await scalekit.webauthn.updateCredential( + "wac_123", + "Work Laptop Passkey" + ); + - label: Python SDK + lang: python + source: |- + res = scalekit_client.webauthn.update_credential( + credential_id="wac_123", + display_name="Work Laptop Passkey" + ) + - label: Go SDK + lang: go + source: |- + resp, err := scalekitClient.WebAuthn().UpdateCredential( + ctx, + "wac_123", + "Work Laptop Passkey", + ) + if err != nil { /* handle err */ } + _ = resp + - label: Java SDK + lang: java + source: |- + UpdateCredentialResponse res = scalekitClient.webauthn() + .updateCredential("wac_123", "Work Laptop Passkey"); + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/WebAuthnServiceUpdateCredentialBody' + required: true +webhooks: + organization.created: + post: + summary: Organization Created + description: Triggered when a new organization is created in Scalekit + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_1234567890 + type: organization.created + object: Organization + occurred_at: '2024-01-15T10:30:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_1234567890 + data: + create_time: '2025-12-09T09:25:02.02Z' + display_name: AcmeCorp + external_id: org_external_123 + id: org_1234567890 + metadata: null + region_code: US + update_time: '2025-12-09T09:25:02.025330364Z' + settings: + features: + - enabled: true + name: sso + - enabled: false + name: dir_sync + display_name: Organization Created + responses: + '200': + description: Webhook received successfully + organization.updated: + post: + summary: Organization Updated + description: Triggered when an organization is updated + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_2345678901 + type: organization.updated + object: Organization + occurred_at: '2024-01-15T10:35:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_1234567890 + data: + create_time: '2025-12-09T09:25:02.02Z' + display_name: AcmeCorp + external_id: org_external_123 + id: org_1234567890 + metadata: null + region_code: US + update_time: '2025-12-09T09:25:02.025330364Z' + settings: + features: + - enabled: true + name: sso + - enabled: false + name: dir_sync + display_name: Organization Updated + responses: + '200': + description: Webhook received successfully + organization.deleted: + post: + summary: Organization Deleted + description: Triggered when an organization is deleted + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_3456789012 + type: organization.deleted + object: Organization + occurred_at: '2024-01-15T10:40:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_1234567890 + data: + create_time: '2025-12-09T09:25:02.02Z' + deleted_at: '2025-12-09T10:25:45.337417Z' + display_name: AcmeCorp + external_id: org_external_123 + id: org_1234567890 + metadata: null + region_code: US + update_time: '2025-12-09T09:25:02.025330364Z' + settings: + features: + - enabled: true + name: sso + - enabled: false + name: dir_sync + display_name: Organization Deleted + responses: + '200': + description: Webhook received successfully + user.signup: + post: + summary: User Signup + description: Triggered when a user signs up to create a new organization + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_1234567890 + type: user.signup + object: OrgMembership + occurred_at: '2024-01-15T10:30:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_102690563312124938 + data: + organization: + id: org_102690563312124938 + create_time: '2025-12-09T10:19:05.48Z' + display_name: '' + external_id: null + metadata: null + region_code: US + update_time: '2025-12-09T12:04:41.386974738Z' + settings: + features: + - enabled: true + name: sso + - enabled: true + name: dir_sync + user: + create_time: '2025-12-09T12:04:41.39Z' + email: amit.ash1996@gmail.com + external_id: '' + id: usr_102701193205121289 + metadata: {} + update_time: '2025-12-09T12:04:41.391988278Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: null + family_name: doe + gender: '' + given_name: John + groups: null + id: usp_102701193205186825 + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + display_name: User Signup + responses: + '200': + description: Webhook received successfully + user.login: + post: + summary: User Login + description: Triggered when a user logs in and a session is created + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_102701193859432713 + type: user.login + object: User + occurred_at: '2025-12-09T12:04:41.781873312Z' + environment_id: env_96736846679245078 + organization_id: org_102701193188409609 + data: + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + last_login_time: '2025-12-09T12:04:41.48Z' + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + family_name: Doe + gender: '' + given_name: John + groups: null + id: usp_102701193205186825 + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + user_session: + absolute_expires_at: '2026-01-08T12:04:41.737394Z' + authenticated_organizations: + - org_102701193188409609 + created_at: '2025-12-09T12:04:41.48Z' + expired_at: null + idle_expires_at: '2025-12-16T12:04:41.737395Z' + last_active_at: '2025-12-09T12:04:41.747206Z' + logout_at: null + organization_id: org_102701193188409609 + session_id: ses_102701193356116233 + status: ACTIVE + updated_at: '2025-12-09T12:04:41.748512Z' + user_id: usr_102701193205121289 + device: + browser: Chrome + browser_version: 142.0.0.0 + device_type: Desktop + ip: 152.59.144.211 + location: + city: Patna + latitude: '25.594095' + longitude: '85.137564' + region: IN + region_subdivision: INBR + os: macOS + os_version: 10.15.7 + user_agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 + display_name: User Login + responses: + '200': + description: Webhook received successfully + user.logout: + post: + summary: User Logout + description: Triggered when a user's session is terminated + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_102708230123160586 + type: user.logout + object: User + occurred_at: '2025-12-09T13:14:35.722070822Z' + environment_id: env_96736846679245078 + organization_id: org_102701193188409609 + data: + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + last_login_time: '2025-12-09T12:04:41.48Z' + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + family_name: Doe + gender: '' + given_name: John + groups: null + id: usp_102701193205186825 + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + user_session: + absolute_expires_at: '2026-01-08T12:04:41.737394Z' + authenticated_organizations: + - org_102701193188409609 + created_at: '2025-12-09T12:04:41.48Z' + expired_at: null + idle_expires_at: '2025-12-16T12:04:41.737395Z' + last_active_at: '2025-12-09T12:04:41.747206Z' + logout_at: null + organization_id: org_102701193188409609 + session_id: ses_102701193356116233 + status: ACTIVE + updated_at: '2025-12-09T12:04:41.748512Z' + user_id: usr_102701193205121289 + device: + browser: Chrome + browser_version: 142.0.0.0 + device_type: Desktop + ip: 152.59.144.211 + location: + city: Patna + latitude: '25.594095' + longitude: '85.137564' + region: IN + region_subdivision: INBR + os: macOS + os_version: 10.15.7 + user_agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 + display_name: User Logout + responses: + '200': + description: Webhook received successfully + user.organization_invitation: + post: + summary: User Organization Invitation + description: Triggered when a user is invited to join an organization + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_4567890123 + type: user.organization_invitation + object: OrgMembership + occurred_at: '2024-01-15T11:00:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_102690563312124938 + data: + organization: + id: org_102690563312124938 + create_time: '2025-12-09T10:19:05.48Z' + display_name: Acme Corp + external_id: org_external_123 + metadata: null + region_code: US + update_time: '2025-12-09T12:04:41.386974738Z' + settings: + features: + - enabled: true + name: sso + - enabled: true + name: dir_sync + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + family_name: Doe + gender: '' + given_name: John + groups: null + id: usp_102701193205186825 + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + display_name: User Organization Invitation + responses: + '200': + description: Webhook received successfully + user.organization_membership_created: + post: + summary: User Organization Membership Created + description: Triggered when a user joins an organization + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_5678901234 + type: user.organization_membership_created + object: OrgMembership + occurred_at: '2024-01-15T11:05:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_102690563312124938 + data: + organization: + id: org_102690563312124938 + create_time: '2025-12-09T10:19:05.48Z' + display_name: Acme Corp + external_id: org_external_123 + metadata: null + region_code: US + update_time: '2025-12-09T12:04:41.386974738Z' + settings: + features: + - enabled: true + name: sso + - enabled: true + name: dir_sync + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + family_name: Doe + gender: '' + given_name: John + groups: null + id: usp_102701193205186825 + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + display_name: User Organization Membership Created + responses: + '200': + description: Webhook received successfully + user.organization_membership_deleted: + post: + summary: User Organization Membership Deleted + description: Triggered when a user's membership in an organization is removed or deleted + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_9012345678 + type: user.organization_membership_deleted + object: OrgMembership + occurred_at: '2024-01-15T11:10:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_102690563312124938 + data: + organization: + id: org_102690563312124938 + create_time: '2025-12-09T10:19:05.48Z' + display_name: Acme Corp + external_id: org_external_123 + metadata: null + region_code: US + update_time: '2025-12-09T12:04:41.386974738Z' + settings: + features: + - enabled: true + name: sso + - enabled: true + name: dir_sync + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + raw_attributes: '{}' + updated_time: '2025-12-09T12:04:41.473087Z' + family_name: Doe + gender: '' + given_name: John + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + display_name: User Organization Membership Deleted + responses: + '200': + description: Webhook received successfully + user.organization_membership_updated: + post: + summary: User Organization Membership Updated + description: Triggered when a user's organization membership is updated, e.g., change of user's role in an organization + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_6789012345 + type: user.organization_membership_updated + object: OrgMembership + occurred_at: '2024-01-15T11:10:00.123456789Z' + environment_id: env_1234567890 + organization_id: org_102690563312124938 + data: + organization: + id: org_102690563312124938 + create_time: '2025-12-09T10:19:05.48Z' + display_name: Acme Corp + external_id: org_external_123 + metadata: null + region_code: US + update_time: '2025-12-09T12:04:41.386974738Z' + settings: + features: + - enabled: true + name: sso + - enabled: true + name: dir_sync + user: + create_time: '2025-12-09T12:04:41.39Z' + email: john.doe@acmecorp.com + external_id: ext_123456789 + id: usr_123456789 + metadata: {} + update_time: '2025-12-09T12:04:41.391988Z' + user_profile: + custom_attributes: null + email_verified: true + external_identities: + - connection_id: conn_97896332307464201 + connection_provider: GOOGLE + connection_type: OAUTH + connection_user_id: '105055379523565727691' + created_time: '2025-12-09T12:04:41.47Z' + is_social: true + last_login_time: '2025-12-09T12:04:41.469311Z' + last_synced_time: '2025-12-09T12:04:41.469311Z' + raw_attributes: '{}' + updated_time: '2025-12-09T12:04:41.473087Z' + family_name: Doe + gender: '' + given_name: John + locale: '' + metadata: {} + name: John Doe + phone_number: '' + phone_number_verified: false + picture: https://lh3.googleusercontent.com/a/abcdef + preferred_username: '' + display_name: User Organization Membership Updated + responses: + '200': + description: Webhook received successfully + organization.directory_enabled: + post: + summary: Directory Enabled + description: Triggered when a directory sync is enabled + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_55136848686613000 + type: organization.directory_enabled + object: Directory + occurred_at: '2025-01-15T08:55:22.802860294Z' + environment_id: env_27758032200925221 + organization_id: org_55135410258444802 + data: + directory_type: SCIM + enabled: true + id: dir_55135622825771522 + organization_id: org_55135410258444802 + provider: OKTA + updated_at: '2025-01-15T08:55:22.792993454Z' + display_name: Directory Enabled + responses: + '200': + description: Webhook received successfully + organization.directory_disabled: + post: + summary: Directory Disabled + description: Triggered when a directory sync is disabled + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_53891640779079756 + type: organization.directory_disabled + object: Directory + occurred_at: '2025-01-06T18:45:21.057814Z' + environment_id: env_53814739859406915 + organization_id: org_53879494091473415 + data: + directory_type: SCIM + enabled: false + id: dir_53879621145330183 + organization_id: org_53879494091473415 + provider: OKTA + updated_at: '2025-01-06T18:45:21.04978184Z' + display_name: Directory Disabled + responses: + '200': + description: Webhook received successfully + organization.directory.user_created: + post: + summary: Directory User Created + description: Triggered when a new directory user is created + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_53891546994442316 + type: organization.directory.user_created + object: DirectoryUser + occurred_at: '2025-01-06T18:44:25.153954Z' + environment_id: env_53814739859406915 + organization_id: org_53879494091473415 + data: + active: true + cost_center: QAUZJUHSTYCN + custom_attributes: + mobile_phone_number: 1-579-4072 + department: HNXJPGISMIFN + division: MJFUEYJOKICN + dp_id: + email: flavio@runolfsdottir.co.duk + employee_id: AWNEDTILGaIZN + family_name: Jaquelin + given_name: Dayton + groups: + - id: dirgroup_12312312312312 + name: Group Name + id: diruser_53891546960887884 + language: se + locale: LLWLEWESPLDC + name: QDRGUZZDYMFU + nickname: DTUODYKGFPPC + organization: AUIITQVUQGVH + organization_id: org_53879494091473415 + phone_number: 1-579-4072 + preferred_username: kuntala1233a + profile: YMIUQUHKGVAX + raw_attributes: {} + title: FKQBHCWJXZSC + user_type: RBQFJSQEFAEH + zoneinfo: America/Araguaina + roles: + - role_name: billing_admin + display_name: Directory User Created + responses: + '200': + description: Webhook received successfully + organization.directory.user_updated: + post: + summary: Directory User Updated + description: Triggered when a directory user is updated + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_53891546994442317 + type: organization.directory.user_updated + object: DirectoryUser + occurred_at: '2025-01-06T18:44:25.153954Z' + environment_id: env_53814739859406915 + organization_id: org_53879494091473415 + data: + id: diruser_12312312312312 + organization_id: org_53879494091473415 + dp_id: + preferred_username: + email: john.doe@example.com + active: true + name: John Doe + roles: + - role_name: billing_admin + groups: + - id: dirgroup_12312312312312 + name: Group Name + given_name: John + family_name: Doe + nickname: Jhonny boy + picture: https://image.com/profile.jpg + phone_number: '1234567892' + address: + postal_code: '64112' + state: Missouri + formatted: 123, Oxford Lane, Kansas City, Missouri, 64112 + custom_attributes: + attribute1: value1 + attribute2: value2 + raw_attributes: {} + display_name: Directory User Updated + responses: + '200': + description: Webhook received successfully + organization.directory.user_deleted: + post: + summary: Directory User Deleted + description: Triggered when a directory user is deleted + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_53891546994442318 + type: organization.directory.user_deleted + object: DirectoryUser + occurred_at: '2025-01-06T18:44:25.153954Z' + environment_id: env_53814739859406915 + organization_id: org_53879494091473415 + data: + id: diruser_12312312312312 + organization_id: org_12312312312312 + dp_id: + email: john.doe@example.com + display_name: Directory User Deleted + responses: + '200': + description: Webhook received successfully + organization.directory.group_created: + post: + summary: Directory Group Created + description: Triggered when a new directory group is created + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_38862741515010639 + type: organization.directory.group_created + object: DirectoryGroup + occurred_at: '2024-09-25T02:26:39.036398577Z' + environment_id: env_32080745237316098 + organization_id: org_38609339635728478 + data: + directory_id: dir_38610496391217780 + display_name: Avengers + external_id: null + id: dirgroup_38862741498233423 + organization_id: org_38609339635728478 + raw_attributes: {} + display_name: Directory Group Created + responses: + '200': + description: Webhook received successfully + organization.directory.group_updated: + post: + summary: Directory Group Updated + description: Triggered when a directory group is updated + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_38864948910162368 + type: organization.directory.group_updated + object: DirectoryGroup + occurred_at: '2024-09-25T02:48:34.745030921Z' + environment_id: env_32080745237316098 + organization_id: org_38609339635728478 + data: + directory_id: dir_38610496391217780 + display_name: Avengers + external_id: + id: dirgroup_38862741498233423 + organization_id: org_38609339635728478 + raw_attributes: {} + display_name: Directory Group Updated + responses: + '200': + description: Webhook received successfully + organization.directory.group_deleted: + post: + summary: Directory Group Deleted + description: Triggered when a directory group is deleted + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_40650399597723966 + type: organization.directory.group_deleted + object: DirectoryGroup + occurred_at: '2024-10-07T10:25:26.289331747Z' + environment_id: env_12205603854221623 + organization_id: org_39802449573184223 + data: + directory_id: dir_39802485862301855 + display_name: Admins + dp_id: 7c66a173-79c6-4270-ac78-8f35a8121e0a + id: dirgroup_40072007005503806 + organization_id: org_39802449573184223 + raw_attributes: {} + display_name: Directory Group Deleted + responses: + '200': + description: Webhook received successfully + organization.sso_created: + post: + summary: SSO Connection Created + description: Triggered when a new SSO connection is created for an organization + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_94567862441607493 + type: organization.sso_created + object: Connection + environment_id: env_74418471961625391 + occurred_at: '2025-10-14T09:27:18.488720586Z' + organization_id: org_83544995172188677 + data: + id: conn_94567862424830277 + organization_id: org_83544995172188677 + connection_type: OIDC + provider: OKTA + display_name: SSO Connection Created + responses: + '200': + description: Webhook received successfully + organization.sso_enabled: + post: + summary: SSO Connection Enabled + description: Triggered when an SSO connection is enabled for an organization + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_94568078213382471 + type: organization.sso_enabled + object: Connection + environment_id: env_74418471961625391 + occurred_at: '2025-10-14T09:29:27.098914861Z' + organization_id: org_83544995172188677 + data: + id: conn_94567862424830277 + organization_id: org_83544995172188677 + connection_type: OIDC + provider: OKTA + enabled: true + status: COMPLETED + display_name: SSO Connection Enabled + responses: + '200': + description: Webhook received successfully + organization.sso_disabled: + post: + summary: SSO Connection Disabled + description: Triggered when an SSO connection is disabled for an organization + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_94557976165089560 + type: organization.sso_disabled + object: Connection + environment_id: env_74418471961625391 + occurred_at: '2025-10-14T07:49:05.809554456Z' + organization_id: org_83544995172188677 + data: + id: conn_83545002856153607 + organization_id: org_83544995172188677 + connection_type: OIDC + provider: OKTA + enabled: false + status: COMPLETED + display_name: SSO Connection Disabled + responses: + '200': + description: Webhook received successfully + organization.sso_deleted: + post: + summary: SSO Connection Deleted + description: Triggered when an SSO connection is deleted for an organization + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_94557997639926040 + type: organization.sso_deleted + object: Connection + environment_id: env_74418471961625391 + occurred_at: '2025-10-14T07:49:18.604546332Z' + organization_id: org_83544995172188677 + data: + id: conn_83545002856153607 + organization_id: org_83544995172188677 + connection_type: OIDC + provider: OKTA + display_name: SSO Connection Deleted + responses: + '200': + description: Webhook received successfully + role.created: + post: + summary: Role Created + description: Triggered when a new role is created + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_1234567890 + type: role.created + object: Role + occurred_at: '2024-01-15T10:30:00.123456789Z' + environment_id: env_1234567890 + data: + description: Viewer role with read-only access + display_name: Viewer + extends: member + id: role_1234567890 + name: viewer + display_name: Role Created + responses: + '200': + description: Webhook received successfully + role.updated: + post: + summary: Role Updated + description: Triggered when a role is updated + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_2345678901 + type: role.updated + object: Role + occurred_at: '2024-01-15T10:35:00.123456789Z' + environment_id: env_1234567890 + data: + description: Updated viewer role with limited permissions + display_name: Viewer + extends: member + id: role_1234567890 + name: viewer + display_name: Role Updated + responses: + '200': + description: Webhook received successfully + role.deleted: + post: + summary: Role Deleted + description: Triggered when a role is deleted + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_3456789012 + type: role.deleted + object: Role + occurred_at: '2024-01-15T10:40:00.123456789Z' + environment_id: env_1234567890 + data: + description: Updated viewer role with limited permissions + display_name: Viewer + extends: member + id: role_1234567890 + name: viewer + display_name: Role Deleted + responses: + '200': + description: Webhook received successfully + permission.created: + post: + summary: Permission Created + description: Triggered when a new permission is created + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_1234567890 + type: permission.created + object: Permission + occurred_at: '2024-01-15T10:30:00.123456789Z' + environment_id: env_1234567890 + data: + description: Permission to manage data + id: perm_1234567890 + name: data:manage + display_name: Permission Created + responses: + '200': + description: Webhook received successfully + permission.updated: + post: + summary: Permission Updated + description: Triggered when a permission is updated + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_2345678901 + type: permission.updated + object: Permission + occurred_at: '2024-01-15T10:35:00.123456789Z' + environment_id: env_1234567890 + data: + description: Updated permission to manage all data + id: perm_1234567890 + name: data:manage + display_name: Permission Updated + responses: + '200': + description: Webhook received successfully + permission.deleted: + post: + summary: Permission Deleted + description: Triggered when a permission is deleted + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ScalekitEvent' + example: + spec_version: '1' + id: evt_3456789012 + type: permission.deleted + object: Permission + occurred_at: '2024-01-15T10:40:00.123456789Z' + environment_id: env_1234567890 + data: + description: Updated permission to manage all data + id: perm_1234567890 + name: data:manage + display_name: Permission Deleted + responses: + '200': + description: Webhook received successfully +components: + securitySchemes: + oauth2: + type: oauth2 + flows: + clientCredentials: + tokenUrl: https://$SCALEKIT_ENVIRONMENT_URL/oauth/token + scopes: + '': No scope required for client credentials flow + schemas: + connectionsConnectionProvider: + type: string + enum: + - OKTA + - GOOGLE + - MICROSOFT_AD + - AUTH0 + - ONELOGIN + - PING_IDENTITY + - JUMPCLOUD + - CUSTOM + - GITHUB + - GITLAB + - LINKEDIN + - SALESFORCE + - MICROSOFT + - IDP_SIMULATOR + - SCALEKIT + - ADFS + connectionsConnectionStatus: + type: string + enum: + - DRAFT + - IN_PROGRESS + - COMPLETED + connectionsConnectionType: + type: string + enum: + - OIDC + - SAML + - PASSWORD + - OAUTH + - PASSWORDLESS + - BASIC + - BEARER + - API_KEY + - WEBAUTHN + - OAUTH_M2M + - TRELLO_OAUTH1 + - GOOGLE_DWD + connectionsListConnection: + type: object + properties: + domains: + description: List of domains configured with this connection + type: array + items: + type: string + examples: + - - yourapp.com + - yourworkspace.com + enabled: + description: Whether the connection is currently active for organization users + type: boolean + examples: + - false + id: + description: Unique identifier of the connection + type: string + examples: + - conn_2123312131125533 + key_id: + description: Alternative identifier for this connection, typically used in frontend applications or URLs + type: string + examples: + - conn_2123312131125533 + organization_id: + description: Unique identifier of the organization that owns this connection + type: string + examples: + - org_2123312131125533 + organization_name: + description: Name of the organization of the connection + type: string + examples: + - Your Organization + provider: + description: Identity provider type (e.g., OKTA, Google, Azure AD) + $ref: '#/components/schemas/connectionsConnectionProvider' + examples: + - CUSTOM + provider_key: + description: Key ID of the identity provider service that handles authentication + type: string + examples: + - google + status: + description: Current configuration status of the connection + $ref: '#/components/schemas/connectionsConnectionStatus' + readOnly: true + examples: + - IN_PROGRESS + type: + description: Authentication protocol used by the connection + $ref: '#/components/schemas/connectionsConnectionType' + examples: + - OIDC + connectionsListConnectionsResponse: + type: object + properties: + connections: + description: List of connections matching the request criteria + type: array + items: + type: object + $ref: '#/components/schemas/connectionsListConnection' + UserServiceResendInviteBody: + type: object + usersInvite: + type: object + properties: + created_at: + description: Timestamp when the invite was originally created. + type: string + format: date-time + examples: + - '2025-07-10T08:00:00Z' + expires_at: + description: The time at which the invite expires. + type: string + format: date-time + examples: + - '2025-12-31T23:59:59Z' + inviter_email: + description: Identifier of the user or system that initiated the invite. + type: string + examples: + - admin@example.com + organization_id: + description: The organization to which the invite belongs. + type: string + examples: + - org_987654321 + resent_at: + description: Timestamp when the invite was last resent, if applicable. + type: string + format: date-time + examples: + - '2025-07-15T09:30:00Z' + resent_count: + description: Number of times the invite has been resent. + type: integer + format: int32 + examples: + - 2 + status: + description: Current status of the invite (e.g., pending, accepted, expired, revoked). + type: string + examples: + - pending_invite + user_id: + description: User ID to whom the invite is sent. May be empty if the user has not signed up yet. + type: string + examples: + - usr_123456 + usersResendInviteResponse: + type: object + properties: + invite: + description: Updated invitation object containing the resent invitation details, including new expiration time and incremented resend counter. + $ref: '#/components/schemas/usersInvite' + examples: + - expires_at: '2025-12-31T23:59:59Z' + organization_id: org_123 + resent_count: 2 + status: pending_invite + user_id: usr_456 + errdetailsDebugInfo: + description: Describes additional debugging info. + type: object + properties: + detail: + description: Additional debugging information provided by the server. + type: string + stack_entries: + description: The stack trace entries indicating where the error occurred. + type: array + items: + type: string + HelpInfoLink: + description: A documentation or reference link. + type: object + properties: + description: + description: Human-readable label for the link (e.g. "User verification flow"). + type: string + url: + description: Absolute URL to the documentation page (e.g. "https://docs.scalekit.com/..."). + type: string + errdetailsHelpInfo: + description: |- + HelpInfo provides documentation links attached to an error response. + When present in ErrorInfo, clients should surface these links to help + developers resolve the error. For example, a missing required field error + may include a link to the relevant guide. + type: object + properties: + links: + description: One or more links relevant to resolving the error. + type: array + items: + type: object + $ref: '#/components/schemas/HelpInfoLink' + errdetailsLocalizedMessageInfo: + type: object + properties: + locale: + type: string + message: + type: string + errdetailsRequestInfo: + description: |- + Contains metadata about the request that clients can attach when filing a bug + or providing other forms of feedback. + type: object + properties: + request_id: + description: |- + An opaque string that should only be interpreted by the service generating + it. For example, it can be used to identify requests in the service's logs. + type: string + serving_data: + description: |- + Any data that was used to serve this request. For example, an encrypted + stack trace that can be sent back to the service provider for debugging. + type: string + errdetailsResourceInfo: + description: Describes the resource that is being accessed. + type: object + properties: + description: + description: |- + Describes what error is encountered when accessing this resource. + For example, updating a cloud project may require the `writer` permission + on the developer console project. + type: string + owner: + type: string + required_permissions: + description: The required permissions needed to access the resource. + type: array + items: + type: string + resource_name: + type: string + user: + type: string + errdetailsToolErrorInfo: + type: object + properties: + execution_id: + type: string + tool_error_code: + type: string + tool_error_message: + type: string + ValidationErrorInfoFieldViolation: + description: A message type used to describe a single bad request field. + type: object + properties: + constraint: + type: string + description: + description: A description of why the request element is bad. + type: string + field: + type: string + errdetailsValidationErrorInfo: + description: |- + Describes violations in a client request. This error type focuses on the + syntactic aspects of the request. + type: object + properties: + field_violations: + description: Describes all violations in a client request. + type: array + items: + type: object + $ref: '#/components/schemas/ValidationErrorInfoFieldViolation' + errdetailsErrorInfo: + type: object + properties: + debug_info: + $ref: '#/components/schemas/errdetailsDebugInfo' + error_code: + type: string + help_info: + $ref: '#/components/schemas/errdetailsHelpInfo' + localized_message_info: + $ref: '#/components/schemas/errdetailsLocalizedMessageInfo' + request_info: + $ref: '#/components/schemas/errdetailsRequestInfo' + resource_info: + $ref: '#/components/schemas/errdetailsResourceInfo' + tool_error_info: + $ref: '#/components/schemas/errdetailsToolErrorInfo' + validation_error_info: + $ref: '#/components/schemas/errdetailsValidationErrorInfo' + commonsRole: + type: object + properties: + display_name: + description: Human-readable name for the role + type: string + examples: + - Dev Team + id: + description: Role ID + type: string + readOnly: true + examples: + - role_79643236410327240 + name: + description: Attribute name/identifier for the role used in system operations and API calls. This should be a machine-readable identifier that follows naming conventions. + type: string + examples: + - team_dev + v1usersCreateMembership: + type: object + properties: + inviter_email: + description: Email address of the user who invited this member. Must be a valid email address. + type: string + examples: + - john.doe@example.com + metadata: + description: Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + roles: + description: Role to assign to the user within the organization + type: array + items: + type: object + $ref: '#/components/schemas/commonsRole' + examples: + - - name: admin + commonsMembershipStatus: + type: string + enum: + - ACTIVE + - INACTIVE + - PENDING_INVITE + - INVITE_EXPIRED + commonsOrganizationMembership: + type: object + properties: + accepted_at: + description: Timestamp when the user accepted the invitation. + type: string + format: date-time + created_at: + description: Timestamp when the invitation was created. + type: string + format: date-time + display_name: + description: Organization display name. This field stores a user-friendly name for the organization that may be different from the formal name, often used for UI display purposes. + type: string + examples: + - Acme Corporation + expires_at: + description: Timestamp when the invitation expired. + type: string + format: date-time + inviter_email: + description: ID of the user who invited this user. + type: string + join_time: + description: Timestamp when the membership was created. Automatically set by the server. + type: string + format: date-time + membership_status: + $ref: '#/components/schemas/commonsMembershipStatus' + metadata: + description: Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + name: + description: Organization name. This field stores the formal organization name used for identification and display purposes. + type: string + examples: + - AcmeCorp + organization_id: + description: Unique identifier for the organization. Immutable and read-only. + type: string + examples: + - org_1234abcd5678efgh + permissions: + description: Effective permissions granted to the user within the organization (including inherited permissions from assigned roles). Lists the specific actions and access rights the user can perform. + type: array + items: + type: string + examples: + - - read_projects + - write_tasks + - manage_users + provisioning_method: + description: |- + How the user was provisioned. + Possible values: + - `jit_using_sso` (Just-in-time provisioning during SSO login) + - `allowed_email_domain` (User joined via allowed email domain matching) + - `org_creator` (User created the organization) + - `direct_provision` (User was directly provisioned via API or SCIM) + - `invitation` (User was invited and accepted an invitation) + type: string + roles: + type: array + items: + type: object + $ref: '#/components/schemas/commonsRole' + commonsIdentityProviderType: + type: string + enum: + - OKTA + - GOOGLE + - MICROSOFT_AD + - AUTH0 + - ONELOGIN + - PING_IDENTITY + - JUMPCLOUD + - CUSTOM + - GITHUB + - GITLAB + - LINKEDIN + - SALESFORCE + - MICROSOFT + - IDP_SIMULATOR + - SCALEKIT + - ADFS + commonsExternalIdentity: + type: object + properties: + connection_id: + description: Unique identifier for the external identity connection. Immutable and read-only. + type: string + readOnly: true + examples: + - conn_1234abcd5678efgh + connection_provider: + description: Type of the identity provider. + $ref: '#/components/schemas/commonsIdentityProviderType' + readOnly: true + examples: + - GOOGLE + connection_type: + description: Name of the external identity connection. + type: string + readOnly: true + examples: + - OAUTH + connection_user_id: + description: Unique identifier for the user in the external identity provider system. Immutable and read-only. + type: string + readOnly: true + examples: + - ext_user_12345 + created_time: + description: Timestamp when this external identity connection was first created. Immutable and read-only. + type: string + format: date-time + readOnly: true + is_social: + description: Indicates if the identity provider is a social provider (true) or enterprise/custom provider (false). Read-only. + type: boolean + readOnly: true + examples: + - true + last_login_time: + description: Timestamp of the user's last successful login via this external identity provider. Automatically updated by the system. + type: string + format: date-time + readOnly: true + last_synced_time: + description: Timestamp of the last data synchronization for this external identity from the provider. Automatically updated by the system. + type: string + format: date-time + readOnly: true + commonsUserProfile: + type: object + properties: + custom_attributes: + description: Custom attributes for extended user profile data and application-specific information. This field stores business-specific user data like department, job title, security clearances, project assignments, or any other organizational attributes your application requires. Unlike system metadata, these attributes are typically managed by administrators or applications and are visible to end users for personalization and business logic. Keys must be 3-25 characters, values must be 1-256 characters, with a maximum of 20 key-value pairs. + type: object + additionalProperties: + type: string + examples: + - department: engineering + security_clearance: level2 + email_verified: + description: Indicates if the user's email address has been verified. Automatically updated by the system. + type: boolean + readOnly: true + examples: + - true + external_identities: + description: List of external identity connections associated with the user profile. + type: array + items: + type: object + $ref: '#/components/schemas/commonsExternalIdentity' + readOnly: true + family_name: + description: The user's family name (last name or surname). This field stores the user's last name and is combined with the given name to create the full display name. The family name is used in formal communications, user listings, and organizational directories throughout the system. Maximum 255 characters allowed. + type: string + examples: + - Doe + gender: + description: The user's gender identity information. This field stores the user's gender identity for personalization, compliance reporting, or organizational analytics purposes. This field supports any string value to accommodate diverse gender identities and should be handled with appropriate privacy considerations according to your organization's policies and applicable regulations. + type: string + examples: + - male + given_name: + description: The user's given name (first name). This field stores the user's first name and is used for personalization, display purposes, and when generating the full display name. The given name appears in user interfaces, formal communications, and user listings throughout the system. Maximum 255 characters allowed. + type: string + examples: + - John + groups: + description: The list of group names the user belongs to within the organization. This field stores the user's group memberships for role-based access control, team assignments, and organizational structure. Groups are typically used for permission management, collaborative access, and organizational hierarchy. Each group name represents a distinct organizational unit or team that the user is associated with. + type: array + items: + type: string + examples: + - - admin + - developer + id: + description: Unique system-generated identifier for the user profile. Immutable and read-only. + type: string + readOnly: true + examples: + - usr_profile_1234abcd5678efgh + locale: + description: The user's preferred language and region settings using BCP-47 format codes. This field customizes the user's experience with localized content, date formats, number formatting, and UI language throughout the system. When not specified, the user inherits the organization's default locale settings. Common values include `en-US`, `en-GB`, `fr-FR`, `de-DE`, and `es-ES`. + type: string + examples: + - en-US + metadata: + description: Raw attributes received from identity providers during authentication. This field stores the original user profile data as received from external IdP systems (SAML, OIDC, etc.) including provider-specific claims and attributes. These fields preserve the complete set of attributes received from the identity source and are used for mapping, synchronization, and audit purposes. Keys must be 3-25 characters, values must be 1-256 characters, with a maximum of 20 key-value pairs. + type: object + additionalProperties: + type: string + examples: + - department: engineering + employee_type: full-time + idp_user_id: '12345' + name: + description: The user's complete display name in formatted form. This field stores the full name as a single string and is typically used when you want to set the complete name rather than using separate given and family names. This name appears in user interfaces, reports, directory listings, and anywhere a formatted display name is needed. This field serves as a formatted display name that complements the individual given_name and family_name fields. + type: string + examples: + - John Michael Doe + phone_number: + description: The user's phone number in E.164 international format. This field stores the phone number for user contact and identification purposes. The phone number must include the country code and be formatted according to E.164 standards (e.g., `+1` for US numbers). This field is optional. + type: string + examples: + - '+14155552671' + phone_number_verified: + description: Indicates if the user's phone number has been verified. Automatically updated by the system. + type: boolean + readOnly: true + examples: + - true + picture: + description: The URL to the user's profile picture or avatar image. This field stores the location of the user's profile photo that appears in user interfaces, directory listings, and collaborative features throughout the system. The URL should point to a publicly accessible image file. Supported formats typically include JPEG, PNG, and GIF. This image is used for visual identification and personalization across the platform. + type: string + examples: + - https://example.com/avatar.jpg + preferred_username: + description: The user's preferred username for display and identification purposes. This field stores a custom username that the user prefers to be known by, which may differ from their email or formal name. This username appears in user interfaces, mentions, informal communications, and collaborative features throughout the system. Maximum 512 characters allowed. + type: string + examples: + - johndoe + usersUser: + type: object + properties: + create_time: + description: Timestamp when the user account was initially created. Automatically set by the server. + type: string + format: date-time + readOnly: true + email: + description: Primary email address for the user. Must be unique across the environment and valid per RFC 5322. + type: string + examples: + - user@example.com + external_id: + description: Your application's unique identifier for this organization, used to link Scalekit with your system. + type: string + examples: + - ext_12345a67b89c + id: + description: Unique system-generated identifier for the user. Immutable once created. + type: string + examples: + - usr_1234abcd5678efgh + last_login_time: + description: Timestamp of the user's most recent successful authentication. Updated automatically. + type: string + format: date-time + readOnly: true + memberships: + description: List of organization memberships. Automatically populated based on group assignments. + type: array + items: + type: object + $ref: '#/components/schemas/commonsOrganizationMembership' + metadata: + description: Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + update_time: + description: Timestamp of the last modification to the user account. Automatically updated by the server. + type: string + format: date-time + readOnly: true + user_profile: + description: User's personal information including name, address, and other profile attributes. + $ref: '#/components/schemas/commonsUserProfile' + usersCreateMembershipResponse: + type: object + properties: + user: + $ref: '#/components/schemas/usersUser' + v1usersUpdateMembership: + type: object + properties: + metadata: + description: Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + roles: + description: Role to assign to the user within the organization + type: array + items: + type: object + $ref: '#/components/schemas/commonsRole' + examples: + - - name: admin + usersUpdateMembershipResponse: + type: object + properties: + user: + $ref: '#/components/schemas/usersUser' + commonsRegionCode: + type: string + enum: + - US + - EU + organizationsOrganizationSettingsFeature: + description: Controls the activation state of a specific organization feature + type: object + title: Organization Feature Toggle + required: + - name + - enabled + properties: + enabled: + description: Whether the feature is enabled (true) or disabled (false) for this organization + type: boolean + examples: + - true + name: + description: 'Feature identifier. Supported values include: "sso" (Single Sign-On), "directory_sync" (Directory Synchronization), "domain_verification" (Domain Verification), "session_policy" (Organization-level session policy override)' + type: string + examples: + - sso + organizationsOrganizationSettings: + description: Configuration options that control organization-level features and capabilities + type: object + title: Organization Settings + properties: + features: + description: List of feature toggles that control organization capabilities such as SSO authentication and directory synchronization + type: array + items: + type: object + $ref: '#/components/schemas/organizationsOrganizationSettingsFeature' + examples: + - - enabled: true + name: sso + - enabled: false + name: directory_sync + examples: + - features: + - enabled: true + name: sso + - enabled: false + name: directory_sync + organizationsOrganization: + type: object + required: + - create_time + properties: + create_time: + description: Timestamp when the organization was created + type: string + format: date-time + title: Created Time + examples: + - '2025-02-15T06:23:44.560000Z' + display_name: + description: Name of the organization. Must be between 1 and 200 characters + type: string + title: Name of the org to be used in display + examples: + - Megasoft + external_id: + description: Your application's unique identifier for this organization, used to link Scalekit with your system. + type: string + title: External Id is useful to store a unique identifier for a given Org that. The unique Identifier can be the id of your tenant / org in your SaaSApp + examples: + - my_unique_id + id: + description: Unique scalekit-generated identifier that uniquely references an organization + type: string + title: Id + examples: + - org_59615193906282635 + logo_url: + description: HTTPS URL of the organization's logo image. Maximum 2048 characters. Must use the https scheme. + type: string + format: uri + maxLength: 2048 + pattern: ^https:// + examples: + - https://cdn.example.com/acme-logo.png + metadata: + description: Key value pairs extension attributes. + type: object + additionalProperties: + type: string + region_code: + description: Geographic region code for the organization. Currently limited to US. + title: Optional regioncode + $ref: '#/components/schemas/commonsRegionCode' + examples: + - US + settings: + title: Organization Settings + $ref: '#/components/schemas/organizationsOrganizationSettings' + slug: + description: DNS-safe slug for dynamic redirect URI resolution. Must be 1-63 chars, lowercase alphanumeric and hyphens, must start and end with an alphanumeric character. Unique per environment. + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([a-z0-9]|-[a-z0-9])*$ + examples: + - acme + update_time: + description: Timestamp when the organization was last updated + type: string + format: date-time + title: Updated time + examples: + - '2025-02-15T06:23:44.560000Z' + organizationsListOrganizationsResponse: + type: object + properties: + next_page_token: + description: Pagination token for the next page of results. Use this token to fetch the next page. + type: string + examples: + - + organizations: + description: List of organization objects + type: array + items: + type: object + $ref: '#/components/schemas/organizationsOrganization' + prev_page_token: + description: Pagination token for the previous page of results. Use this token to fetch the previous page. + type: string + examples: + - + total_size: + description: Total number of organizations in the environment. + type: integer + format: int64 + examples: + - 30 + v1organizationsCreateOrganization: + type: object + required: + - display_name + properties: + display_name: + description: Name of the organization. Must be between 1 and 200 characters. + type: string + examples: + - Megasoft Inc + external_id: + description: Your application's unique identifier for this organization, used to link Scalekit with your system. + type: string + examples: + - my_unique_id + logo_url: + description: HTTPS URL of the organization's logo image. Maximum 2048 characters. Must use the https scheme. + type: string + format: uri + maxLength: 2048 + pattern: ^https:// + examples: + - https://cdn.example.com/acme-logo.png + metadata: + type: object + additionalProperties: + type: string + slug: + description: DNS-safe slug for dynamic redirect URI resolution (e.g. acme for https://acme.example.com/callback). Lowercase alphanumeric and hyphens, 1-63 chars, must start and end with alphanumeric, unique per environment. + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([a-z0-9]|-[a-z0-9])*$ + examples: + - acme + organizationsCreateOrganizationResponse: + type: object + properties: + organization: + description: The newly created organization containing its ID, settings, and metadata + $ref: '#/components/schemas/organizationsOrganization' + organizationsGetOrganizationResponse: + type: object + properties: + organization: + description: The newly created organization + $ref: '#/components/schemas/organizationsOrganization' + v1organizationsUpdateOrganization: + description: For update messages ensure the indexes are same as the base model itself. + type: object + properties: + display_name: + description: Name of the organization to display in the UI. Must be between 1 and 200 characters + type: string + examples: + - Acme Corporation + external_id: + description: Your application's unique identifier for this organization, used to link Scalekit with your system + type: string + examples: + - tenant_12345 + logo_url: + description: HTTPS URL of the organization's logo image. Maximum 2048 characters. Must use the https scheme. + type: string + format: uri + maxLength: 2048 + pattern: ^https:// + examples: + - https://cdn.example.com/acme-logo.png + metadata: + description: Custom key-value pairs to store with the organization. Keys must be 3-25 characters, values must be 1-256 characters. Maximum 10 pairs allowed. + type: object + additionalProperties: + type: string + examples: + - industry: technology + slug: + description: DNS-safe slug for dynamic redirect URI resolution. Lowercase alphanumeric and hyphens, 1-63 chars, must start and end with alphanumeric, unique per environment. + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([a-z0-9]|-[a-z0-9])*$ + examples: + - acme + organizationsUpdateOrganizationResponse: + type: object + properties: + organization: + description: Updated organization details + $ref: '#/components/schemas/organizationsOrganization' + organizationsLink: + type: object + properties: + expire_time: + description: Expiry time of the link. The link is valid for 1 minute. + type: string + format: date-time + examples: + - '2024-02-06T14:48:00Z' + id: + description: Unique Identifier for the link + type: string + examples: + - lnk_123123123123123 + location: + description: Location of the link. This is the URL that can be used to access the Admin portal. The link is valid for 1 minute + type: string + examples: + - https://scalekit.com/portal/lnk_123123123123123 + organizationsGeneratePortalLinkResponse: + type: object + properties: + link: + description: 'Contains the generated admin portal link details. The link URL can be shared with organization administrators to set up: Single Sign-On (SSO) authentication and directory synchronization' + $ref: '#/components/schemas/organizationsLink' + rolesRolePermission: + type: object + title: RolePermissions represents a permission with role source information + properties: + create_time: + type: string + format: date-time + description: + type: string + id: + type: string + name: + type: string + role_name: + description: Name of the role from which this permission was sourced + type: string + examples: + - admin_role + update_time: + type: string + format: date-time + v1rolesRole: + type: object + properties: + default_creator: + description: Indicates if this role is the default creator role for new organizations. + type: boolean + examples: + - true + default_member: + description: Indicates if this role is the default member role for new users. + type: boolean + examples: + - true + dependent_roles_count: + description: Number of roles that extend from this role (dependent roles count). Read-only field. + type: integer + format: int32 + examples: + - 3 + description: + description: Detailed description of the role's purpose and capabilities. Maximum 2000 characters. + type: string + examples: + - Can create, edit, and publish content but cannot delete or manage users + display_name: + description: Human-readable display name for the role. Used in user interfaces and reports. + type: string + examples: + - Content Editor + extends: + description: Name of the base role that this role extends. Enables hierarchical role inheritance. + type: string + examples: + - admin_role + id: + description: Unique system-generated identifier for the role. Immutable once created. + type: string + readOnly: true + examples: + - role_1234abcd5678efgh + is_org_role: + description: Indicates if this role is an organization role. + type: boolean + examples: + - true + name: + description: Unique name identifier for the role. Must be alphanumeric with underscores, 1-100 characters. + type: string + examples: + - content_editor + permissions: + description: List of permissions with role source information. Only included when 'include' parameter is specified in the request. + type: array + items: + type: object + $ref: '#/components/schemas/rolesRolePermission' + examples: + - - description: Read Content + name: read:content + role_name: admin_role + - description: Write Content + name: write:content + role_name: editor_role + rolesListOrganizationRolesResponse: + type: object + properties: + roles: + description: List of roles objects + type: array + items: + type: object + $ref: '#/components/schemas/v1rolesRole' + v1rolesCreateOrganizationRole: + type: object + properties: + description: + description: Description of the organization's role + type: string + examples: + - Organization Viewer Role will be used only for viewing the objects + display_name: + description: Display name of the organization's role + type: string + examples: + - Organization Viewer Role + extends: + description: Base role name for hierarchical roles + type: string + examples: + - admin_role + name: + description: Unique name of the organization's role + type: string + examples: + - org_viewer_role + permissions: + description: List of permission names to assign to this role. Permissions must exist in the current environment. + type: array + items: + type: string + examples: + - - read:users + - write:documents + rolesCreateOrganizationRoleResponse: + type: object + properties: + role: + $ref: '#/components/schemas/v1rolesRole' + rolesGetOrganizationRoleResponse: + type: object + properties: + role: + $ref: '#/components/schemas/v1rolesRole' + v1rolesUpdateRole: + type: object + properties: + description: + description: Detailed description of the role's purpose, capabilities, and intended use cases. Maximum 2000 characters. + type: string + examples: + - Can create, edit, publish, and approve content. Cannot delete content or manage user accounts. + display_name: + description: Human-readable display name for the role. Used in user interfaces, reports, and user-facing communications. + type: string + examples: + - Senior Content Editor + extends: + description: Name of the base role that this role extends. Enables hierarchical role inheritance where this role inherits all permissions from the base role. + type: string + examples: + - content_editor + permissions: + description: List of permission names to assign to this role. When provided, this replaces all existing role-permission mappings. Permissions must exist in the current environment. Maximum 100 permissions per role. + type: array + items: + type: string + examples: + - - read:content + - write:content + - publish:content + - approve:content + rolesUpdateOrganizationRoleResponse: + type: object + properties: + role: + $ref: '#/components/schemas/v1rolesRole' + RolesServiceUpdateDefaultOrganizationRolesBody: + type: object + properties: + default_member_role: + description: Unique name of the default member role + type: string + examples: + - member + rolesUpdateDefaultOrganizationRolesResponse: + type: object + properties: + default_member: + description: Updated default member role + $ref: '#/components/schemas/v1rolesRole' + examples: + - description: Role for regular members + display_name: Member Role + id: role_0987654321 + name: member + clientsCustomClaim: + type: object + properties: + key: + description: The name of the custom claim. Must be between 1 and 128 characters. Use descriptive names that clearly indicate the claim's purpose. + type: string + examples: + - environment + value: + description: The value of the custom claim. This value will be included in access tokens issued to the client. + type: string + examples: + - production + clientsClientSecretStatus: + description: |- + ClientSecretStatus indicates whether a client secret can be used for authentication. + ACTIVE secrets can be used for authentication while INACTIVE secrets cannot. + + - INACTIVE: The secret is inactive and cannot be used for authentication + type: string + enum: + - INACTIVE + clientsClientSecret: + description: A secure credential used for authenticating an API client. Each client can have multiple secrets for key rotation purposes. + type: object + title: Client Secret + properties: + create_time: + description: The timestamp when this secret was created. This field is automatically set by the server and cannot be modified. + type: string + format: date-time + examples: + - '2024-01-05T14:48:00Z' + created_by: + description: The identifier of the user or system that created this secret. This field helps track who created the secret for audit and compliance purposes. + type: string + examples: + - user_12345 + expire_time: + description: The timestamp when this secret will expire. After this time, the secret cannot be used for authentication regardless of its status. If not set, the secret does not expire. + type: string + format: date-time + examples: + - '2025-01-05T14:48:00Z' + id: + description: The unique identifier for this client secret. This ID is used to reference the secret in API requests for management operations like updating or deleting the secret. + type: string + examples: + - sec_1234abcd5678efgh + last_used_time: + description: The timestamp when this secret was last used for authentication. This field helps track secret usage for security monitoring and identifying unused secrets that may be candidates for rotation. + type: string + format: date-time + examples: + - '2024-02-15T10:30:00Z' + plain_secret: + description: The full plaintext secret value. This field is only populated when the secret is first created and is never stored by the server. It must be securely stored by the client application as it cannot be retrieved again. + type: string + examples: + - sec_1234567890abcdefghijklmnopqrstuvwxyz + secret_suffix: + description: A suffix that helps identify this secret. This is the last few characters of the full secret value but is not sufficient for authentication. Helps identify which secret is being used in logs and debugging. + type: string + examples: + - xyzw + status: + description: The current status of this secret. A secret must be ACTIVE to be used for authentication. INACTIVE secrets cannot be used for authentication but are retained for audit purposes. + $ref: '#/components/schemas/clientsClientSecretStatus' + examples: + - INACTIVE + update_time: + description: The timestamp when this secret was last updated. This field is automatically updated by the server when the secret's status changes or other properties are modified. + type: string + format: date-time + examples: + - '2024-01-10T09:12:00Z' + clientsM2MClient: + type: object + properties: + audience: + description: The intended recipients of access tokens issued to this client. Each audience value should be a URI that identifies an API or service. + type: array + items: + type: string + examples: + - - https://api.example.com + client_id: + description: The unique identifier for this API client. This ID is used to identify the client in API requests and logs. It is automatically generated when the client is created and cannot be modified. + type: string + examples: + - m2morg_1231234233424344 + create_time: + description: The timestamp when this API client was created. This field is automatically set by the server and cannot be modified. + type: string + format: date-time + examples: + - '2024-01-05T14:48:00Z' + custom_claims: + description: Additional claims included in access tokens issued to this client. These claims provide context about the client and can be used for authorization decisions. + type: array + items: + type: object + $ref: '#/components/schemas/clientsCustomClaim' + description: + description: A detailed description of the client's purpose and usage. This helps administrators understand what the client is used for. + type: string + examples: + - Service account for automated deployment processes + expiry: + description: Expiry time in seconds for the token generated by the client + type: string + format: int64 + examples: + - 3600 + is_cimd: + description: Indicates if the client was created via Client ID Metadata Document (CIMD). CIMD clients can update their own configuration according to the CIMD specification. + type: boolean + examples: + - false + is_dcr: + description: Indicates if the client was created via Dynamic Client Registration (DCR). Clients created through DCR may have different management and lifecycle policies compared to those created manually. + type: boolean + examples: + - false + metadata_uri: + description: The URI to the client's metadata, which is utilized to obtain the client's configuration details + type: string + examples: + - https://example.com/client-metadata.json + name: + description: The display name of the API client. This name helps identify the client in the dashboard and logs. + type: string + examples: + - GitHub Actions Deployment Service + organization_id: + description: The ID of the organization that owns this API client. This ID is used to associate the client with the correct organization and enforce organization-specific access controls. + type: string + examples: + - org_1231234233424344 + redirect_uris: + description: The redirect URI for this API client. This URI is used in the OAuth 2.0 authorization flow to redirect users after authentication. + type: array + items: + type: string + examples: + - - https://example.com/callback + resource_id: + description: The ID of the resource associated with this M2M client. This field is used to link the client to a specific resource in the system. + type: string + examples: + - app_1231234233424344 + scopes: + description: The OAuth 2.0 scopes granted to this client. These scopes determine what resources and actions the client can access. + type: array + items: + type: string + examples: + - - deploy:resources + - read:deployments + secrets: + description: List of client secrets associated with this client. Each secret can be used for authentication, but only the most recently created secret is typically active. Secrets are stored securely and their values are never returned after creation. + type: array + items: + type: object + $ref: '#/components/schemas/clientsClientSecret' + update_time: + description: The timestamp when this API client was last updated. This field is automatically updated by the server whenever the client's configuration changes. + type: string + format: date-time + examples: + - '2024-01-05T14:48:00Z' + clientsListOrganizationClientsResponse: + description: Response message containing a paginated list of API clients for the specified organization. + type: object + title: List Organization Clients Response + properties: + clients: + description: List of API client objects for the organization. Each client includes its configuration, metadata, and active secrets (without exposing actual secret values). + type: array + title: List of organization API clients + items: + type: object + $ref: '#/components/schemas/clientsM2MClient' + next_page_token: + description: Pagination token for the next page of results. Use this token to fetch the next page. + type: string + title: Pagination token for the next page of results + examples: + - + prev_page_token: + description: Pagination token for the previous page of results. Use this token to fetch the previous page. + type: string + title: Pagination token for the previous page of results + examples: + - + total_size: + description: Total number of API clients in the organization. + type: integer + format: int64 + title: Total number of clients in the organization + examples: + - 30 + clientsOrganizationClient: + type: object + properties: + audience: + description: The intended recipients of the access tokens issued to this client. Each audience value should be a URI that identifies the API or service that will validate the token. + type: array + items: + type: string + examples: + - - https://api.example.com/api/analytics + - https://deployment-api.acmecorp.com + custom_claims: + description: Additional claims to be included in access tokens issued to this client. These claims provide context about the client and can be used for authorization decisions. Keep claims minimal to avoid increasing token size. + type: array + items: + type: object + $ref: '#/components/schemas/clientsCustomClaim' + examples: + - - key: environment + value: production + - key: service + value: deployment + description: + description: A detailed explanation of the client's purpose and usage. This helps administrators understand what the client is used for and who manages it. + type: string + examples: + - Service account for GitHub Actions to deploy resources to production + expiry: + description: Expiry time in seconds for the token generated by the client + type: string + format: int64 + examples: + - 3600 + name: + description: A descriptive name for the API client that helps identify its purpose. This name is displayed in the dashboard and logs. Must be between 1 and 128 characters. + type: string + examples: + - GitHub Actions Deployment Service + scopes: + description: OAuth 2.0 scopes that define the permissions granted to this client. Each scope represents a specific permission or set of permissions. The client can only access resources that match its granted scopes. + type: array + items: + type: string + examples: + - - deploy:resources + - read:deployments + clientsCreateOrganizationClientResponse: + type: object + properties: + client: + description: Details of the created client + $ref: '#/components/schemas/clientsM2MClient' + plain_secret: + description: Client secret value (only returned once at creation) + type: string + examples: + - CdExsdErfccxDDssddfffgfeFHH1 + clientsGetOrganizationClientResponse: + type: object + properties: + client: + description: Details of the requested client + $ref: '#/components/schemas/clientsM2MClient' + clientsUpdateOrganizationClientResponse: + type: object + properties: + client: + description: Updated details of the client + $ref: '#/components/schemas/clientsM2MClient' + clientsCreateOrganizationClientSecretResponse: + type: object + properties: + plain_secret: + description: Client secret value (only returned once at creation) + type: string + examples: + - m2morg_client_secret_xyz123 + secret: + description: Details of the created client secret + $ref: '#/components/schemas/clientsClientSecret' + connectionsConfigurationType: + type: string + enum: + - DISCOVERY + - MANUAL + domainsVerificationMethod: + type: string + enum: + - ADMIN + - DNS + - NOT_APPLICABLE + domainsVerificationStatus: + type: string + enum: + - PENDING + - VERIFIED + - FAILED + - AUTO_VERIFIED + domainsDomain: + type: object + properties: + create_time: + description: Timestamp when the domain was first created. + type: string + format: date-time + examples: + - '2025-09-01T12:14:43.100000Z' + domain: + description: The business domain name that was configured for allowed email domain functionality (e.g., company.com, subdomain.company.com). + type: string + examples: + - customerdomain.com + domain_type: + example: ORGANIZATION_DOMAIN + environment_id: + description: The environment ID where this domain is configured. + type: string + examples: + - env_58345499215790610 + id: + description: Scalekit-generated unique identifier for this domain record. + type: string + examples: + - dom_88351643129225005 + organization_id: + description: The organization to which the domain belongs. + type: string + examples: + - org_81667076086825451 + update_time: + description: Timestamp when the domain was last updated. + type: string + format: date-time + examples: + - '2025-09-01T12:14:43.110455Z' + verification_method: + description: |- + Method that determines how domain ownership is verified. + - ADMIN: domain is marked verified without DNS validation, typically by an admin. + - DNS: domain must be verified by adding a TXT record to your DNS configuration. + - NOT_APPLICABLE: verification does not apply to this domain type. + $ref: '#/components/schemas/domainsVerificationMethod' + examples: + - ADMIN + verification_status: + description: |- + Verification status of the domain. + - PENDING: DNS TXT record has not been validated yet. + - VERIFIED: domain confirmed via DNS TXT record validation or admin approval. + - AUTO_VERIFIED: domain verified automatically without DNS changes. + - FAILED: DNS TXT record was not validated within the verification window. + $ref: '#/components/schemas/domainsVerificationStatus' + examples: + - AUTO_VERIFIED + connectionsGoogleDWDConfig: + type: object + properties: + scopes: + description: OAuth 2.0 scopes to request. + type: array + items: + type: string + service_account_json: + description: 'Google Cloud service account JSON key. Write-only: reads return a masked value.' + type: string + token_uri: + description: Google token endpoint. Defaults to https://oauth2.googleapis.com/token. + type: string + connectionsOptionalScopes: + type: object + properties: + field_name: + description: Name of the field in which scope should be sent in the authentication request. This is required by some identity providers that expect scopes to be sent in a custom field instead of the standard 'scope' parameter. + type: string + examples: + - optional_scope or bot_scope + scopes: + description: List of optional scopes that can be requested during authentication + type: array + items: + type: string + examples: + - - scope1 + - scope2 + connectionsOAuthConnectionConfig: + type: object + properties: + access_type: + description: Access Type + type: string + examples: + - offline + app_name: + description: Application name used by providers that require it as an authorize query parameter (e.g., Trello's app_name). + type: string + examples: + - My Trello App + authorize_uri: + description: Authorize URI + type: string + examples: + - https://youridp.com/service/oauth/authorize + client_id: + description: Client ID + type: string + examples: + - oauth_client_id + client_secret: + description: Client Secret + type: string + examples: + - oauth_client_secret + custom_scope_name: + description: Custom Scope Name + type: string + examples: + - user_scope + is_cimd: + description: Indicates whether this connection was registered using Client ID Metadata Document (CIMD) instead of Dynamic Client Registration. + type: boolean + readOnly: true + examples: + - true + optional_scopes: + description: Optional scopes configuration for identity providers that support or require additional scopes to be sent in a custom field during authentication requests. + $ref: '#/components/schemas/connectionsOptionalScopes' + pkce_enabled: + description: PKCE Enabled + type: boolean + examples: + - true + prompt: + description: Prompt for the user + type: string + examples: + - none + redirect_uri: + description: Redirect URI + type: string + examples: + - https://yourapp.com/service/oauth/redirect + scopes: + description: OIDC Scopes + type: array + items: + type: string + examples: + - - openid + - profile + sync_user_profile_on_login: + description: Indicates whether user profiles should be synchronized with the identity provider upon each log-in. + type: boolean + examples: + - true + tenant_id: + description: Microsoft Entra tenant ID. Required when using a single-tenant or multi-tenant app registered in Microsoft Entra. Leave empty to use the common endpoint. + type: string + examples: + - xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + token_access_type: + description: Token Access Type + type: string + examples: + - offline + token_uri: + description: Token URI + type: string + examples: + - https://youridp.com/service/oauth/token + use_platform_creds: + description: Use Scalekit credentials + type: boolean + examples: + - true + user_info_uri: + description: User Info URI + type: string + examples: + - https://youridp.com/service/oauth/userinfo + connectionsOIDCScope: + type: string + enum: + - openid + - profile + - email + - address + - phone + connectionsTokenAuthType: + type: string + enum: + - URL_PARAMS + - BASIC_AUTH + connectionsOIDCConnectionConfig: + type: object + properties: + authorize_uri: + description: Authorize URI + type: string + examples: + - https://youridp.com/service/oauth/authorize + backchannel_logout_redirect_uri: + description: backchannel logout redirect uri where idp sends logout_token + type: string + readOnly: true + examples: + - https://yourapp.com/sso/v1/oidc/conn_1234/backchannel-logout + client_id: + description: Client ID + type: string + examples: + - oauth_client_id + client_secret: + description: Client Secret + type: string + examples: + - oauth_client_secret + discovery_endpoint: + description: Discovery Endpoint + type: string + examples: + - https://youridp.com/service/oauth/.well-known/openid-configuration + idp_logout_required: + description: Enable IDP logout + type: boolean + examples: + - true + issuer: + description: Issuer URL + type: string + examples: + - https://youridp.com/service/oauth + jit_provisioning_with_sso_enabled: + description: Indicates if Just In Time user provisioning is enabled for the connection + type: boolean + examples: + - true + jwks_uri: + description: JWKS URI + type: string + examples: + - https://youridp.com/service/oauth/jwks + pkce_enabled: + description: PKCE Enabled + type: boolean + examples: + - true + post_logout_redirect_uri: + description: post logout redirect uri + type: string + readOnly: true + examples: + - https://yourapp.com/sso/v1/oidc/conn_1234/logout/callback + redirect_uri: + description: Redirect URI + type: string + examples: + - https://yourapp.com/sso/v1/oidc/conn_1234/callback + scopes: + description: OIDC Scopes + type: array + items: + $ref: '#/components/schemas/connectionsOIDCScope' + examples: + - - openid + - profile + sync_user_profile_on_login: + description: Indicates whether user profiles should be synchronized with the identity provider upon each log-in. + type: boolean + examples: + - true + token_auth_type: + description: Token Auth Type + $ref: '#/components/schemas/connectionsTokenAuthType' + examples: + - URL_PARAMS + token_uri: + description: Token URI + type: string + examples: + - https://youridp.com/service/oauth/token + user_info_uri: + description: User Info URI + type: string + examples: + - https://youridp.com/service/oauth/userinfo + connectionsCodeChallengeType: + type: string + enum: + - NUMERIC + - ALPHANUMERIC + connectionsPasswordlessType: + type: string + enum: + - LINK + - OTP + - LINK_OTP + connectionsPasswordLessConfig: + type: object + properties: + code_challenge_length: + description: Code Challenge Length + type: integer + format: int64 + examples: + - 6 + code_challenge_type: + description: Code Challenge Type + $ref: '#/components/schemas/connectionsCodeChallengeType' + examples: + - NUMERIC + enforce_same_browser_origin: + description: Enforce Same Browser Origin + type: boolean + examples: + - true + frequency: + description: Link Frequency + type: integer + format: int64 + examples: + - 1 + regenerate_passwordless_credentials_on_resend: + description: 'Regenerate the ' + type: boolean + examples: + - true + type: + description: Passwordless Type + $ref: '#/components/schemas/connectionsPasswordlessType' + examples: + - LINK + validity: + description: Link Validity in Seconds + type: integer + format: int64 + examples: + - 600 + connectionsIDPCertificate: + type: object + properties: + certificate: + description: IDP Certificate + type: string + create_time: + description: Certificate Creation Time + type: string + format: date-time + examples: + - '2021-09-01T00:00:00Z' + expiry_time: + description: Certificate Expiry Time + type: string + format: date-time + examples: + - '2021-09-01T00:00:00Z' + id: + description: Certificate ID + type: string + examples: + - cert_123123123123 + issuer: + description: Certificate Issuer + type: string + examples: + - https://youridp.com/service/saml + connectionsNameIdFormat: + type: string + enum: + - UNSPECIFIED + - EMAIL + - TRANSIENT + - PERSISTENT + connectionsRequestBinding: + type: string + enum: + - HTTP_POST + - HTTP_REDIRECT + connectionsSAMLSigningOptions: + type: string + title: enums all + enum: + - NO_SIGNING + - SAML_ONLY_RESPONSE_SIGNING + - SAML_ONLY_ASSERTION_SIGNING + - SAML_RESPONSE_ASSERTION_SIGNING + - SAML_RESPONSE_OR_ASSERTION_SIGNING + connectionsSAMLConnectionConfigResponse: + type: object + properties: + allow_idp_initiated_login: + description: Allow IDP Initiated Login + type: boolean + examples: + - true + assertion_encrypted: + description: Assertion Encrypted + type: boolean + examples: + - true + certificate_id: + description: Certificate ID + type: string + examples: + - cer_35585423166144613 + default_redirect_uri: + description: Default Redirect URI + type: string + examples: + - https://yourapp.com/service/saml/redirect + force_authn: + description: Force Authn + type: boolean + examples: + - true + idp_certificates: + description: IDP Certificates + type: array + items: + type: object + $ref: '#/components/schemas/connectionsIDPCertificate' + idp_entity_id: + description: IDP Entity ID + type: string + examples: + - https://youridp.com/service/saml + idp_metadata_url: + description: IDP Metadata URL + type: string + examples: + - https://youridp.com/service/saml/metadata + idp_name_id_format: + description: IDP Name ID Format + $ref: '#/components/schemas/connectionsNameIdFormat' + examples: + - EMAIL + idp_slo_request_binding: + description: IDP SLO Request Binding + $ref: '#/components/schemas/connectionsRequestBinding' + examples: + - HTTP_POST + idp_slo_required: + description: Enable IDP logout + type: boolean + examples: + - true + idp_slo_url: + description: IDP SLO URL + type: string + examples: + - https://youridp.com/service/saml/slo + idp_sso_request_binding: + description: IDP SSO Request Binding + $ref: '#/components/schemas/connectionsRequestBinding' + examples: + - HTTP_POST + idp_sso_url: + description: IDP SSO URL + type: string + examples: + - https://youridp.com/service/saml/sso + jit_provisioning_with_sso_enabled: + description: Indicates if Just In Time user provisioning is enabled for the connection + type: boolean + examples: + - true + saml_signing_option: + description: SAML Signing Option + $ref: '#/components/schemas/connectionsSAMLSigningOptions' + examples: + - SAML_ONLY_RESPONSE_SIGNING + sp_assertion_url: + description: SP Assertion URL + type: string + examples: + - https://youridp.com/service/saml/assertion + sp_entity_id: + description: SP Entity ID + type: string + examples: + - https://yourapp.com/service/saml + sp_metadata_url: + description: SP Metadata URL + type: string + examples: + - https://youridp.com/service/saml/metadata + sp_slo_url: + description: Service Provider SLO url + type: string + readOnly: true + examples: + - https://yourapp.com/sso/v1/saml/conn_1234/slo/callback + sync_user_profile_on_login: + description: Indicates whether user profiles should be synchronized with the identity provider upon each log-in. + type: boolean + examples: + - true + ui_button_title: + description: UI Button Title + type: string + examples: + - Login with SSO + want_request_signed: + description: Want Request Signed + type: boolean + examples: + - true + connectionsStaticAuthConfig: + type: object + properties: + static_config: + type: object + WebAuthConfigurationAttestation: + type: object + title: Attestation preferences for registration + properties: + conveyance_preference: + type: string + title: Conveyance preference + enterprise_approved_ids: + type: array + title: Enterprise-approved IDs (optional allowlist when enterprise attestation is used) + items: + type: string + WebAuthConfigurationAuthenticatorSelection: + type: object + properties: + authenticator_attachment: + type: string + user_verification: + type: string + title: User verification requirement + WebAuthConfigurationAuthenticators: + type: object + properties: + desired_authenticator_status: + description: provides the list of statuses which are considered undesirable for status report validation purposes. Should be used with validate_status set to true. + type: array + items: + type: string + default: '[]' + undesired_authenticator_status: + description: provides the list of statuses which are considered undesirable for status report validation purposes. Should be used with validate_status set to true. + type: array + items: + type: string + default: '[''ATTESTATION_KEY_COMPROMISE'', ''USER_VERIFICATION_BYPASS'', ''USER_KEY_REMOTE_COMPROMISE'', ''USER_KEY_PHYSICAL_COMPROMISE'', ''REVOKED'']' + validate_anchors: + description: when set to true enables the validation of the attestation statement against the trust anchor from the metadata statement. + type: boolean + validate_attestation_type: + description: when set to true enables the validation of the attestation statements type against the known types the authenticator can produce. + type: boolean + validate_entry: + description: requires that the provided metadata has an entry for the given authenticator to be considered valid. By default an AAGUID which has a zero value should fail validation if validate_entry_permit_zero_aaguid is not provided with the value of true. + type: boolean + validate_entry_permit_zero_aaguid: + description: is an option that permits a zero'd AAGUID from an attestation statement to automatically pass metadata validations. Generally helpful to use with validate_entry. + type: boolean + validate_status: + description: when set to true enables the validation of the attestation statements AAGUID against the desired and undesired lists + type: boolean + WebAuthConfigurationRp: + type: object + title: Rp contains relying party identifiers and origins + properties: + ids: + type: array + title: |- + Relying party IDs (derived from environment domain and verified custom domain) + At least one required; must be hostnames without scheme or path + items: + type: string + origins: + type: array + title: |- + Allowed origins corresponding to the RP IDs (https://) + At least one required; must be HTTPS origins + items: + type: string + WebAuthConfigurationTimeout: + type: object + properties: + login: + description: Login timeout duration + type: string + default: '"300s"' + login_uvd: + description: Login timeout duration when user verification is discouraged + type: string + default: '"300s"' + registration: + description: Registration timeout duration + type: string + default: '"300s"' + registration_uvd: + description: Registration timeout duration when user verification is discouraged + type: string + default: '"300s"' + connectionsWebAuthConfiguration: + type: object + title: WebAuthConfiguration defines WebAuthn (passkeys) configuration limited to RP and Attestation + properties: + attestation: + $ref: '#/components/schemas/WebAuthConfigurationAttestation' + authenticator_selection: + $ref: '#/components/schemas/WebAuthConfigurationAuthenticatorSelection' + authenticators: + $ref: '#/components/schemas/WebAuthConfigurationAuthenticators' + enable_auto_registration: + description: Enable auto registration for WebAuthn + type: boolean + enable_conditional_login: + description: Allow autofill of passkeys in login page + type: boolean + rp: + $ref: '#/components/schemas/WebAuthConfigurationRp' + show_passkey_button: + description: Show passkey button on login screen + type: boolean + timeout: + $ref: '#/components/schemas/WebAuthConfigurationTimeout' + connectionsConnection: + type: object + properties: + attribute_mapping: + description: 'Maps identity provider attributes to user profile fields. For example, {''email'': ''user.mail'', ''name'': ''user.displayName''}.' + type: object + additionalProperties: + type: string + configuration_type: + description: 'How the connection was configured: DISCOVERY (automatic configuration) or MANUAL (administrator configured)' + $ref: '#/components/schemas/connectionsConfigurationType' + examples: + - MANUAL + debug_enabled: + description: Enables testing mode that allows non-HTTPS endpoints. Should only be enabled in development environments, never in production. + type: boolean + examples: + - true + domains: + description: Domain associated with this connection, used for domain-based authentication flows. + type: array + items: + type: object + $ref: '#/components/schemas/domainsDomain' + examples: + - - name: example.com + enabled: + description: Controls whether users can sign in using this connection. When false, the connection exists but cannot be used for authentication. + type: boolean + examples: + - false + google_dwd_config: + description: Configuration details for Google Domain-Wide Delegation. Present only when type is GOOGLE_DWD. + $ref: '#/components/schemas/connectionsGoogleDWDConfig' + id: + description: Unique identifier for this connection. Used in API calls to reference this specific connection. + type: string + examples: + - conn_2123312131125533 + key_id: + description: Alternative identifier for this connection, typically used in frontend applications or URLs. + type: string + oauth_config: + description: Configuration details for OAuth connections. Present only when type is OAUTH. + $ref: '#/components/schemas/connectionsOAuthConnectionConfig' + oidc_config: + description: Configuration details for OpenID Connect (OIDC) connections. Present only when type is OIDC. + $ref: '#/components/schemas/connectionsOIDCConnectionConfig' + organization_id: + description: Identifier of the organization that owns this connection. Connections are typically scoped to a single organization. + type: string + examples: + - org_2123312131125533 + passwordless_config: + description: Configuration details for Magic Link authentication. Present only when type is MAGIC_LINK. + $ref: '#/components/schemas/connectionsPasswordLessConfig' + provider: + description: Identity provider service that handles authentication (such as OKTA, Google, Azure AD, or a custom provider) + $ref: '#/components/schemas/connectionsConnectionProvider' + examples: + - OKTA + provider_key: + description: Key ID of the identity provider service that handles authentication + type: string + examples: + - google + saml_config: + description: Configuration details for SAML connections. Present only when type is SAML. + $ref: '#/components/schemas/connectionsSAMLConnectionConfigResponse' + static_config: + description: Static configuration for custom connections. Present only when type is BASIC, BEARER, API_KEY, or custom. + $ref: '#/components/schemas/connectionsStaticAuthConfig' + status: + description: Current configuration status of the connection. Possible values include IN_PROGRESS, CONFIGURED, and ERROR. + $ref: '#/components/schemas/connectionsConnectionStatus' + readOnly: true + examples: + - IN_PROGRESS + test_connection_uri: + description: URI that can be used to test this connection. Visit this URL to verify the connection works correctly. + type: string + examples: + - https://auth.example.com/test-connection/conn_2123312131125533 + type: + description: Authentication protocol used by this connection. Can be OIDC (OpenID Connect), SAML, OAUTH, or MAGIC_LINK. + $ref: '#/components/schemas/connectionsConnectionType' + examples: + - OIDC + webauthn_config: + description: Configuration details for WebAuthn (passkeys). Present only when type is WEBAUTHN. + $ref: '#/components/schemas/connectionsWebAuthConfiguration' + connectionsGetConnectionResponse: + type: object + properties: + connection: + description: Complete connection details including provider configuration, protocol settings, status, and all metadata. Contains everything needed to understand the connection's current state. + $ref: '#/components/schemas/connectionsConnection' + connectionsToggleConnectionResponse: + type: object + properties: + enabled: + description: Current state of the connection after the operation. True means the connection is now enabled and can be used for authentication. + type: boolean + examples: + - true + error_message: + description: Error message if the operation fails + type: string + examples: + - placeholder + directoriesAttributeMapping: + type: object + properties: + key: + type: string + map_to: + type: string + directoriesAttributeMappings: + type: object + properties: + attributes: + type: array + items: + type: object + $ref: '#/components/schemas/directoriesAttributeMapping' + directoriesDirectoryProvider: + type: string + enum: + - OKTA + - GOOGLE + - MICROSOFT_AD + - AUTH0 + - ONELOGIN + - JUMPCLOUD + - PING_IDENTITY + directoriesDirectoryType: + type: string + enum: + - SCIM + - LDAP + - POLL + directoriesRoleAssignment: + type: object + properties: + group_id: + description: group ID for the role mapping + type: string + examples: + - dirgroup_121312434123 + role_name: + type: string + directoriesRoleAssignments: + type: object + properties: + assignments: + type: array + items: + type: object + $ref: '#/components/schemas/directoriesRoleAssignment' + directoriesSecretStatus: + type: string + enum: + - INACTIVE + directoriesSecret: + type: object + properties: + create_time: + description: Creation Time + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + directory_id: + description: Directory ID + type: string + examples: + - dir_12362474900684814 + expire_time: + description: Expiry Time + type: string + format: date-time + examples: + - '2025-10-01T00:00:00Z' + id: + type: string + last_used_time: + description: Last Used Time + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + secret_suffix: + description: Secret Suffix + type: string + examples: + - Nzg5 + status: + description: Secret Status + $ref: '#/components/schemas/directoriesSecretStatus' + examples: + - INACTIVE + directoriesStats: + type: object + properties: + group_updated_at: + description: Max time of Group Updated At for Directory + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + total_groups: + description: Total Groups in the Directory + type: integer + format: int32 + examples: + - 10 + total_users: + description: Total Users in the Directory + type: integer + format: int32 + examples: + - 10 + user_updated_at: + description: Max time of User Updated At for Directory + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + directoriesDirectory: + type: object + properties: + attribute_mappings: + description: Mappings between directory attributes and Scalekit user and group attributes + $ref: '#/components/schemas/directoriesAttributeMappings' + directory_endpoint: + description: The endpoint URL generated by Scalekit for synchronizing users and groups from the Directory Provider + type: string + examples: + - https://yourapp.scalekit.com/api/v1/directoies/dir_123212312/scim/v2 + directory_provider: + description: Identity provider connected to this directory + $ref: '#/components/schemas/directoriesDirectoryProvider' + examples: + - OKTA + directory_type: + description: Type of the directory, indicating the protocol or standard used for synchronization + $ref: '#/components/schemas/directoriesDirectoryType' + examples: + - SCIM + email: + description: Email Id associated with Directory whose access will be used for polling + type: string + examples: + - john.doe@scalekit.cloud + enabled: + description: Indicates whether the directory is currently enabled and actively synchronizing users and groups + type: boolean + examples: + - true + groups_tracked: + description: It indicates if all groups are tracked or select groups are tracked + type: string + examples: + - ALL + id: + description: Unique identifier of the directory + type: string + examples: + - dir_121312434123312 + last_synced_at: + description: Timestamp of the last successful synchronization of users and groups from the Directory Provider + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + name: + description: Name of the directory, typically representing the connected Directory provider + type: string + examples: + - Azure AD + organization_id: + description: Unique identifier of the organization to which the directory belongs + type: string + examples: + - org_121312434123312 + role_assignments: + description: Role assignments associated with the directory, defining group based role assignments + $ref: '#/components/schemas/directoriesRoleAssignments' + secrets: + description: List of secrets used for authenticating and synchronizing with the Directory Provider + type: array + items: + type: object + $ref: '#/components/schemas/directoriesSecret' + stats: + description: Statistics and metrics related to the directory, such as synchronization status and error counts + $ref: '#/components/schemas/directoriesStats' + status: + description: Directory Status + type: string + examples: + - IN_PROGRESS + total_groups: + description: Total number of groups in the directory + type: integer + format: int32 + examples: + - 10 + total_users: + description: Total number of users in the directory + type: integer + format: int32 + examples: + - 10 + directoriesListDirectoriesResponse: + type: object + properties: + directories: + description: List of directories associated with the organization + type: array + items: + type: object + $ref: '#/components/schemas/directoriesDirectory' + directoriesDirectoryGroup: + type: object + properties: + display_name: + description: Display Name + type: string + examples: + - Admins + group_detail: + description: Complete Group Details Payload + type: object + id: + description: Group ID + type: string + examples: + - dirgroup_121312434123312 + total_users: + description: Total Users in the Group + type: integer + format: int32 + examples: + - 10 + updated_at: + description: Updated At + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + directoriesListDirectoryGroupsResponse: + type: object + properties: + groups: + description: List of directory groups retrieved from the specified directory + type: array + items: + type: object + $ref: '#/components/schemas/directoriesDirectoryGroup' + next_page_token: + description: Token to retrieve the next page of results. Use this token in the 'page_token' field of the next request + type: string + prev_page_token: + description: Token to retrieve the previous page of results. Use this token in the 'page_token' field of the next request + type: string + total_size: + description: Total number of groups matching the request criteria, regardless of pagination + type: integer + format: int64 + directoriesDirectoryUser: + type: object + properties: + email: + description: Email + type: string + examples: + - johndoe + emails: + description: Emails + type: array + items: + type: string + family_name: + description: Last Name + type: string + examples: + - Doe + given_name: + description: First Name + type: string + examples: + - John + groups: + description: Groups + type: array + items: + type: object + $ref: '#/components/schemas/directoriesDirectoryGroup' + id: + description: User ID + type: string + examples: + - diruser_121312434123312 + preferred_username: + description: Preferred Username + type: string + examples: + - johndoe + updated_at: + description: Updated At + type: string + format: date-time + examples: + - '2024-10-01T00:00:00Z' + user_detail: + description: Complete User Details Payload + type: object + directoriesListDirectoryUsersResponse: + type: object + properties: + next_page_token: + description: Token for pagination. Use this token in the 'page_token' field of the next request to fetch the subsequent page of users + type: string + prev_page_token: + description: Token for pagination. Use this token in the 'page_token' field of the next request to fetch the prior page of users + type: string + total_size: + description: Total number of users available in the directory that match the request criteria + type: integer + format: int64 + users: + description: List of directory users retrieved from the specified directory + type: array + items: + type: object + $ref: '#/components/schemas/directoriesDirectoryUser' + directoriesGetDirectoryResponse: + type: object + properties: + directory: + description: Detailed information about the requested directory + $ref: '#/components/schemas/directoriesDirectory' + directoriesToggleDirectoryResponse: + type: object + properties: + enabled: + description: Specifies the directory's state after the toggle operation. A value of `true` indicates that the directory is enabled and actively synchronizing users and groups. A value of `false` means the directory is disabled, halting synchronization + type: boolean + examples: + - true + error_message: + description: Contains a human-readable error message if the toggle operation encountered an issue. If the operation was successful, this field will be empty + type: string + examples: + - The directory is already enabled + domainsListDomainResponse: + type: object + properties: + domains: + description: Array of domain objects containing all domain details including verification status and configuration. + type: array + items: + type: object + $ref: '#/components/schemas/domainsDomain' + page_number: + description: Current page number in the pagination sequence. + type: integer + format: int32 + examples: + - 1 + page_size: + description: Number of domains returned in this page. + type: integer + format: int32 + examples: + - 1 + domainsDomainType: + type: string + enum: + - ALLOWED_EMAIL_DOMAIN + - ORGANIZATION_DOMAIN + x-enum-varnames: + - ORGANIZATION_DOMAIN + - ALLOWED_EMAIL_DOMAIN + v1domainsCreateDomain: + type: object + properties: + domain: + description: The domain name to be configured. Must be a valid business domain you control. Public and disposable domains (gmail.com, outlook.com, etc.) are automatically blocked for security. + type: string + examples: + - customerdomain.com + domain_type: + description: | + The domain type. + - ALLOWED_EMAIL_DOMAIN: trusted domain used to suggest the organization in the organization switcher during sign-in/sign-up. + - ORGANIZATION_DOMAIN: SSO discovery domain used to route users to the correct SSO provider and enforce SSO. + $ref: '#/components/schemas/domainsDomainType' + examples: + - ORGANIZATION_DOMAIN + domainsCreateDomainResponse: + type: object + properties: + domain: + description: The newly created domain object with all configuration details and system-generated identifiers. + $ref: '#/components/schemas/domainsDomain' + domainsGetDomainResponse: + type: object + properties: + domain: + description: The requested domain object with complete details including domain type, timestamps and configuration. + $ref: '#/components/schemas/domainsDomain' + commonsTimeUnit: + type: string + enum: + - MINUTES + - HOURS + - DAYS + organizationsSessionPolicyType: + type: string + enum: + - APPLICATION + - CUSTOM + organizationsOrganizationSessionPolicySettings: + type: object + properties: + absolute_session_timeout: + description: The absolute session timeout value. The unit is specified by absolute_session_timeout_unit. Omitted when policy_source is 'environment'. + type: integer + format: int32 + examples: + - 360 + absolute_session_timeout_unit: + description: 'Unit for absolute_session_timeout. Accepted values: ''minutes'', ''hours'', ''days''. Responses always return ''minutes''.' + $ref: '#/components/schemas/commonsTimeUnit' + examples: + - minutes + idle_session_timeout: + description: The idle session timeout value. The unit is specified by idle_session_timeout_unit. Omitted when idle_session_timeout_enabled is false or policy_source is 'environment'. + type: integer + format: int32 + examples: + - 84 + idle_session_timeout_enabled: + description: Whether idle session timeout is enabled for this organization. Omitted when policy_source is 'environment'. + type: boolean + examples: + - true + idle_session_timeout_unit: + description: 'Unit for idle_session_timeout. Accepted values: ''minutes'', ''hours'', ''days''. Responses always return ''minutes''.' + $ref: '#/components/schemas/commonsTimeUnit' + examples: + - minutes + policy_source: + description: Policy source. 'APPLICATION' means the organization inherits the application-level session policy. 'CUSTOM' means organization-specific timeout values are active. + $ref: '#/components/schemas/organizationsSessionPolicyType' + examples: + - CUSTOM + organizationsGetOrganizationSessionPolicyResponse: + type: object + properties: + policy: + description: The session policy for the organization. + $ref: '#/components/schemas/organizationsOrganizationSessionPolicySettings' + OrganizationServiceUpdateOrganizationSessionPolicyBody: + type: object + properties: + absolute_session_timeout: + description: The absolute session timeout value. The unit is specified by absolute_session_timeout_unit. Omit when policy_source is APPLICATION. + type: integer + format: int32 + examples: + - 360 + absolute_session_timeout_unit: + description: 'Unit for absolute_session_timeout. Accepted values: ''MINUTES'', ''HOURS'', ''DAYS''. Defaults to MINUTES.' + $ref: '#/components/schemas/commonsTimeUnit' + examples: + - MINUTES + idle_session_timeout: + description: The idle session timeout value. The unit is specified by idle_session_timeout_unit. Omit when idle_session_timeout_enabled is false. + type: integer + format: int32 + examples: + - 84 + idle_session_timeout_enabled: + description: Whether idle session timeout is enabled. Omit when policy_source is APPLICATION. + type: boolean + examples: + - true + idle_session_timeout_unit: + description: 'Unit for idle_session_timeout. Accepted values: ''MINUTES'', ''HOURS'', ''DAYS''. Defaults to MINUTES.' + $ref: '#/components/schemas/commonsTimeUnit' + examples: + - MINUTES + policy_source: + description: Policy source. Send 'APPLICATION' to revert to application defaults. Send 'CUSTOM' with timeout values to activate a custom policy. + $ref: '#/components/schemas/organizationsSessionPolicyType' + examples: + - CUSTOM + organizationsUpdateOrganizationSessionPolicyResponse: + type: object + properties: + policy: + description: The updated session policy for the organization. + $ref: '#/components/schemas/organizationsOrganizationSessionPolicySettings' + organizationsOrganizationUserManagementSettings: + type: object + properties: + max_allowed_users: + description: Maximum number of users allowed in the organization. When nil (not set), there feature is not enabled. When explicitly set to zero, it also means no limit. When set to a positive integer, it enforces the maximum user limit. + type: integer + format: int32 + examples: + - 100 + OrganizationServiceUpsertUserManagementSettingsBody: + type: object + properties: + settings: + description: The new values for the setting fields to patch. + $ref: '#/components/schemas/organizationsOrganizationUserManagementSettings' + organizationsUpsertUserManagementSettingsResponse: + type: object + properties: + settings: + description: The updated setting. + $ref: '#/components/schemas/organizationsOrganizationUserManagementSettings' + usersListOrganizationUsersResponse: + type: object + properties: + next_page_token: + description: Opaque token for retrieving the next page of results. Empty if there are no more pages. + type: string + examples: + - eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0= + prev_page_token: + description: Opaque token for retrieving the previous page of results. Empty for the first page. + type: string + examples: + - eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9 + total_size: + description: Total number of users matching the request criteria, regardless of pagination. + type: integer + format: int64 + examples: + - 1042 + users: + description: List of user objects for the current page. May contain fewer entries than requested page_size. + type: array + items: + type: object + $ref: '#/components/schemas/usersUser' + usersCreateUserProfile: + type: object + properties: + custom_attributes: + description: Custom attributes for extended user profile data. Keys (3-25 chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + security_clearance: level2 + family_name: + description: User's family name. Maximum 255 characters. + type: string + examples: + - Doe + gender: + description: User's gender identity. + type: string + examples: + - male + given_name: + description: User's given name. Maximum 255 characters. + type: string + examples: + - John + groups: + description: List of group names the user belongs to. Each group name must be 1-250 characters + type: array + items: + type: string + examples: + - - engineering + - managers + locale: + description: User's localization preference in BCP-47 format. Defaults to organization settings. + type: string + examples: + - en-US + metadata: + description: System-managed key-value pairs for internal tracking. Keys (3-25 chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - account_status: active + signup_source: mobile_app + name: + description: Full name in display format. Typically combines first_name and last_name. + type: string + examples: + - John Michael Doe + phone_number: + description: Phone number in E.164 international format. Required for SMS-based authentication. + type: string + examples: + - '+14155552671' + picture: + description: URL to the user's profile picture or avatar. + type: string + examples: + - https://example.com/avatar.jpg + preferred_username: + description: User's preferred username for display purposes. + type: string + examples: + - John Michael Doe + usersCreateUser: + type: object + properties: + email: + description: Primary email address for the user. Must be unique across the environment and valid per RFC 5322. + type: string + examples: + - user@example.com + external_id: + description: Your application's unique identifier for this organization, used to link Scalekit with your system. + type: string + examples: + - ext_12345a67b89c + membership: + description: List of organization memberships. Automatically populated based on group assignments. + $ref: '#/components/schemas/v1usersCreateMembership' + metadata: + description: Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + user_profile: + description: User's personal information including name, address, and other profile attributes. + $ref: '#/components/schemas/usersCreateUserProfile' + usersCreateUserAndMembershipResponse: + type: object + properties: + user: + $ref: '#/components/schemas/usersUser' + usersPermission: + type: object + properties: + description: + description: Description of what the permission allows + type: string + examples: + - Allows creating new user accounts + id: + description: Unique identifier for the permission + type: string + readOnly: true + examples: + - perm_1234abcd5678efgh + name: + description: Unique name identifier for the permission + type: string + examples: + - users:create + usersListUserPermissionsResponse: + type: object + properties: + permissions: + description: List of permissions the user has access to + type: array + items: + type: object + $ref: '#/components/schemas/usersPermission' + usersListUserRolesResponse: + type: object + properties: + roles: + description: List of roles assigned to the user + type: array + items: + type: object + $ref: '#/components/schemas/commonsRole' + usersSearchOrganizationUsersResponse: + type: object + properties: + next_page_token: + description: Token for retrieving the next page of results. Empty if there are no more pages. + type: string + examples: + - eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0= + prev_page_token: + description: Token for retrieving the previous page of results. Empty if this is the first page. + type: string + examples: + - eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9 + total_size: + description: Total number of users matching the request criteria, regardless of pagination. + type: integer + format: int64 + examples: + - 1042 + users: + description: List of matching users. + type: array + items: + type: object + $ref: '#/components/schemas/usersUser' + passwordlessResendPasswordlessRequest: + type: object + properties: + auth_request_id: + description: The authentication request identifier from the original send passwordless email request. Use this to resend the Verification Code (OTP) or Magic Link to the same email address. + type: string + examples: + - h5Y8kT5RVwaea5WEgW4n-6C-aO_-fuTUW7Vb9-Rh3AcY9qxZqQ + authpasswordlessPasswordlessType: + type: string + enum: + - OTP + - LINK + - LINK_OTP + passwordlessSendPasswordlessResponse: + type: object + properties: + auth_request_id: + description: Unique identifier for this passwordless authentication request. Use this ID to resend emails. + type: string + readOnly: true + examples: + - h5Y8kT5RVwaea5WEgW4n-6C-aO_-fuTUW7Vb9-Rh3AcY9qxZqQ + expires_at: + description: Unix timestamp (seconds since epoch) when the passwordless authentication will expire. After this time, the OTP or magic link will no longer be valid. + type: string + format: int64 + readOnly: true + examples: + - 1748696575 + expires_in: + description: Number of seconds from now until the passwordless authentication expires. This is a convenience field calculated from the expires_at timestamp. + type: integer + format: int64 + readOnly: true + examples: + - 300 + passwordless_type: + description: Type of passwordless authentication that was sent via email. OTP sends a numeric code, LINK sends a clickable magic link, and LINK_OTP provides both options for user convenience. + $ref: '#/components/schemas/authpasswordlessPasswordlessType' + examples: + - OTP + passwordlessTemplateType: + type: string + enum: + - SIGNIN + - SIGNUP + passwordlessSendPasswordlessRequest: + type: object + properties: + email: + description: Email address where the passwordless authentication credentials will be sent. Must be a valid email format. + type: string + examples: + - john.doe@example.com + expires_in: + description: Time in seconds until the passwordless authentication expires. If not specified, defaults to 300 seconds (5 minutes) + type: integer + format: int64 + examples: + - 300 + magiclink_auth_uri: + description: Your application's callback URL where users will be redirected after clicking the magic link in their email. The link token will be appended as a query parameter as link_token + type: string + examples: + - https://yourapp.com/auth/passwordless/callback + state: + description: Custom state parameter that will be returned unchanged in the verification response. Use this to maintain application state between the authentication request and callback, such as the intended destination after login + type: string + examples: + - d62ivasry29lso + template: + description: Specifies the authentication intent for the passwordless request. Use SIGNIN for existing users or SIGNUP for new user registration. This affects the email template and user experience flow. + $ref: '#/components/schemas/passwordlessTemplateType' + examples: + - SIGNIN + template_variables: + description: |- + A set of key-value pairs to personalize the email template. + + * You may include up to 30 key-value pairs. + * The following variable names are reserved by the system and cannot be supplied: `otp`, `expiry_time_relative`, `link`, `expire_time`, `expiry_time`. + * Every variable referenced in your email template must be included as a key-value pair. + + Use these variables to insert custom information, such as a team name, URL or the user's employee ID. All variables are interpolated before the email is sent, regardless of the email provider. + type: object + additionalProperties: + type: string + examples: + - custom_variable_key: custom_variable_value + passwordlessVerifyPasswordLessRequest: + type: object + properties: + auth_request_id: + description: The authentication request identifier returned from the send passwordless email endpoint. Required when verifying OTP codes to link the verification with the original request. + type: string + examples: + - h5Y8kT5RVwaea5WEgW4n-6C-aO_-fuTUW7Vb9-Rh3AcY9qxZqQ + code: + description: The Verification Code (OTP) received via email. This is typically a 6-digit numeric code that users enter manually to verify their identity. + type: string + examples: + - '123456' + link_token: + description: The unique token from the magic link URL received via email. Extract this token when users click the magic link and are redirected to your application to later verify the user. + type: string + examples: + - afe9d61c-d80d-4020-a8ee-61765ab71cb3 + passwordlessVerifyPasswordLessResponse: + type: object + properties: + email: + description: Email address of the successfully authenticated user. This confirms which email account was verified through the passwordless flow. + type: string + readOnly: true + examples: + - john.doe@example.com + passwordless_type: + description: The type of passwordless authentication that was successfully verified, confirming which method the user completed. + $ref: '#/components/schemas/authpasswordlessPasswordlessType' + examples: + - OTP + state: + description: The custom state parameter that was provided in the original authentication request, returned unchanged. Use this to restore your application's context after authentication. + type: string + readOnly: true + examples: + - kdt7yiag28t341fr1 + template: + description: Specifies which email template to choose. For User Signin choose SIGNIN and for User Signup use SIGNUP + $ref: '#/components/schemas/passwordlessTemplateType' + examples: + - SIGNIN + rolesPermission: + type: object + title: Permission Entity + properties: + create_time: + type: string + format: date-time + description: + type: string + id: + type: string + is_scalekit_permission: + description: Indicates whether this permission is predefined by Scalekit + type: boolean + examples: + - true + name: + type: string + update_time: + type: string + format: date-time + rolesListPermissionsResponse: + type: object + properties: + next_page_token: + description: Token to retrieve next page of results + type: string + examples: + - token_def456 + permissions: + type: array + items: + type: object + $ref: '#/components/schemas/rolesPermission' + prev_page_token: + description: Token to retrieve previous page of results + type: string + examples: + - token_def456 + total_size: + description: Total number of permissions available + type: integer + format: int64 + examples: + - 150 + v1rolesCreatePermission: + type: object + properties: + description: + description: Description of the permission + type: string + examples: + - Allows user to read documents from the system + name: + description: Unique name/ID of the permission + type: string + examples: + - read:documents + rolesCreatePermissionResponse: + type: object + properties: + permission: + $ref: '#/components/schemas/rolesPermission' + rolesGetPermissionResponse: + type: object + properties: + permission: + $ref: '#/components/schemas/rolesPermission' + rolesUpdatePermissionResponse: + type: object + properties: + permission: + $ref: '#/components/schemas/rolesPermission' + rolesListRolesResponse: + type: object + properties: + roles: + description: List of all roles in the environment with their metadata and optionally their permissions. + type: array + items: + type: object + $ref: '#/components/schemas/v1rolesRole' + examples: + - - display_name: Administrator + id: role_1234abcd5678efgh + name: admin + - display_name: Viewer + id: role_9876zyxw5432vuts + name: viewer + v1rolesCreateRole: + type: object + properties: + description: + description: Detailed description of the role's purpose, capabilities, and intended use cases. Maximum 2000 characters. + type: string + examples: + - Can create, edit, and publish content but cannot delete content or manage user accounts + display_name: + description: Human-readable display name for the role. Used in user interfaces, reports, and user-facing communications. + type: string + examples: + - Content Editor + extends: + description: Name of the base role that this role extends. Enables hierarchical role inheritance where this role inherits all permissions from the base role. + type: string + examples: + - viewer + name: + description: Unique name identifier for the role. Must be alphanumeric with underscores, 1-64 characters. This name is used in API calls and cannot be changed after creation. + type: string + examples: + - content_editor + permissions: + description: List of permission names to assign to this role. Permissions must exist in the current environment. Maximum 100 permissions per role. + type: array + items: + type: string + examples: + - - read:content + - write:content + - publish:content + rolesCreateRoleResponse: + type: object + properties: + role: + description: The created role object with system-generated ID and all configuration details. + $ref: '#/components/schemas/v1rolesRole' + examples: + - description: Can edit content + display_name: Content Editor + id: role_1234abcd5678efgh + name: content_editor + rolesUpdateDefaultRole: + type: object + properties: + id: + type: string + name: + description: Unique name of the role + type: string + examples: + - creator + rolesUpdateDefaultRolesRequest: + type: object + properties: + default_creator: + description: Default creator role (deprecated - use default_creator_role field instead) + $ref: '#/components/schemas/rolesUpdateDefaultRole' + examples: + - description: Role for creating resources + display_name: Creator Role + id: role_1234567890 + name: creator + default_creator_role: + description: Name of the role to set as the default creator role. This role will be automatically assigned to users who create new resources in the environment. Must be a valid role name that exists in the environment. + type: string + examples: + - creator + default_member: + description: Default member role (deprecated - use default_member_role field instead) + $ref: '#/components/schemas/rolesUpdateDefaultRole' + examples: + - description: Role for regular members + display_name: Member Role + id: role_0987654321 + name: member + default_member_role: + description: Name of the role to set as the default member role. This role will be automatically assigned to new users when they join the environment. Must be a valid role name that exists in the environment. + type: string + examples: + - member + rolesUpdateDefaultRolesResponse: + type: object + properties: + default_creator: + description: The role that is now set as the default creator role for the environment. Contains complete role information including permissions and metadata. + $ref: '#/components/schemas/v1rolesRole' + examples: + - description: Role for creating resources + display_name: Creator Role + id: role_1234567890 + name: creator + default_member: + description: The role that is now set as the default member role for the environment. Contains complete role information including permissions and metadata. + $ref: '#/components/schemas/v1rolesRole' + examples: + - description: Role for regular members + display_name: Member Role + id: role_0987654321 + name: member + rolesGetRoleResponse: + type: object + properties: + role: + description: The complete role object with all metadata, permissions, and inheritance details. + $ref: '#/components/schemas/v1rolesRole' + examples: + - dependent_roles_count: 2 + display_name: Content Editor + id: role_1234abcd5678efgh + name: content_editor + permissions: + - name: read:content + rolesUpdateRoleResponse: + type: object + properties: + role: + description: The updated role object with all current configuration details. + $ref: '#/components/schemas/v1rolesRole' + examples: + - description: Can edit and approve content + display_name: Senior Editor + id: role_1234abcd5678efgh + name: content_editor + rolesListDependentRolesResponse: + type: object + properties: + roles: + description: List of dependent roles + type: array + items: + type: object + $ref: '#/components/schemas/v1rolesRole' + rolesListRolePermissionsResponse: + type: object + properties: + permissions: + description: List of permissions directly assigned to the role + type: array + items: + type: object + $ref: '#/components/schemas/rolesPermission' + RolesServiceAddPermissionsToRoleBody: + type: object + properties: + permission_names: + description: List of permission names to add to the role + type: array + items: + type: string + rolesAddPermissionsToRoleResponse: + type: object + properties: + permissions: + description: List of all permissions belonging to the role after addition + type: array + items: + type: object + $ref: '#/components/schemas/rolesPermission' + rolesListEffectiveRolePermissionsResponse: + type: object + properties: + permissions: + description: List of all effective permissions including those inherited from base roles + type: array + items: + type: object + $ref: '#/components/schemas/rolesPermission' + rolesGetRoleUsersCountResponse: + type: object + properties: + count: + description: Number of users associated with the role + type: string + format: int64 + examples: + - 10 + sessionsAuthenticatedClients: + description: AuthenticatedClients represents an authenticated client in a session along with its organization context. + type: object + properties: + client_id: + description: Unique identifier of the authenticated client application. + type: string + examples: + - skc_1234567890 + organization_id: + description: Active or last active Organization ID associated with the authenticated client. + type: string + examples: + - org_1234567890 + v1sessionsLocation: + type: object + properties: + city: + description: City name where the session originated based on IP geolocation. Approximate location derived from IP address. + type: string + examples: + - San Francisco + latitude: + description: 'Latitude coordinate of the estimated location. Decimal format (e.g., ''37.7749''). Note: Represents IP geolocation center and may not be precise.' + type: string + examples: + - '37.7749' + longitude: + description: 'Longitude coordinate of the estimated location. Decimal format (e.g., ''-122.4194''). Note: Represents IP geolocation center and may not be precise.' + type: string + examples: + - '-122.4194' + region: + description: Geographic region name derived from IP geolocation. Represents the country-level location (e.g., 'United States', 'France'). + type: string + examples: + - United States + region_subdivision: + description: Regional subdivision code or name (e.g., state abbreviation for US, province for Canada). Two-letter ISO format when applicable. + type: string + examples: + - CA + sessionsDeviceDetails: + type: object + properties: + browser: + description: 'Browser name and family extracted from the user agent. Examples: Chrome, Safari, Firefox, Edge, Mobile Safari.' + type: string + examples: + - Chrome + browser_version: + description: Version of the browser application. Represents the specific release version of the browser being used. + type: string + examples: + - 120.0.0.0 + device_type: + description: 'Categorized device type classification. Possible values: ''desktop'' (traditional computers), ''mobile'' (smartphones and small tablets), ''tablet'' (large tablets), ''other''. Useful for displaying session information by device category.' + type: string + examples: + - desktop + ip: + description: IP address of the device that initiated the session. This is the public-facing IP address used to connect to the application. Useful for security audits and geographic distribution analysis. + type: string + examples: + - 192.0.2.1 + location: + description: 'Geographic location information derived from IP address geolocation. Includes country, region, city, and coordinates. Note: Based on IP location data and may not represent the user''s exact physical location.' + $ref: '#/components/schemas/v1sessionsLocation' + os: + description: 'Operating system name extracted from the user agent and device headers. Examples: macOS, Windows, Linux, iOS, Android.' + type: string + examples: + - macOS + os_version: + description: Version of the operating system. Represents the specific OS release the device is running. + type: string + examples: + - '14.2' + user_agent: + description: Complete HTTP User-Agent header string from the client request. Contains browser type, version, and operating system information. Used for detailed device fingerprinting and user agent analysis. + type: string + examples: + - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 + sessionsSessionDetails: + type: object + properties: + absolute_expires_at: + description: Hard expiration timestamp for the session regardless of user activity. The session will be forcibly terminated at this time. This represents the maximum session lifetime from creation. + type: string + format: date-time + examples: + - '2025-01-22T10:30:00Z' + authenticated_clients: + description: 'Details of the authenticated clients for this session: client ID and organization context.' + type: array + items: + type: object + $ref: '#/components/schemas/sessionsAuthenticatedClients' + authenticated_organizations: + description: List of organization IDs that have been authenticated for this user within the current session. Contains all organizations where the user has successfully completed SSO or authentication. + type: array + items: + type: string + examples: + - - org_123 + - org_456 + created_at: + description: Timestamp indicating when the session was created. This is set once at session creation and remains constant throughout the session lifetime. + type: string + format: date-time + examples: + - '2025-01-15T10:30:00Z' + device: + description: Complete device metadata associated with this session including browser, operating system, device type, and geographic location based on IP address. + $ref: '#/components/schemas/sessionsDeviceDetails' + expired_at: + description: Timestamp when the session was terminated. Null if the session is still active. Set when the session expires due to reaching idle_expires_at or absolute_expires_at timeout, or when administratively revoked. Not set for user-initiated logout (see logout_at instead). + type: string + format: date-time + examples: + - '2025-01-15T12:00:00Z' + idle_expires_at: + description: Projected expiration timestamp if the session remains idle without user activity. This timestamp is recalculated with each user activity. Session will be automatically terminated at this time if no activity occurs. + type: string + format: date-time + examples: + - '2025-01-15T11:30:00Z' + last_active_at: + description: Timestamp of the most recent user activity detected in this session. Updated on each API request or user interaction. Used to determine if a session has exceeded the idle timeout threshold. + type: string + format: date-time + examples: + - '2025-01-15T10:55:30Z' + logout_at: + description: Timestamp when the user explicitly logged out from the session. Null if the user has not logged out. When set, indicates the session ended due to explicit user logout rather than timeout. + type: string + format: date-time + examples: + - '2025-01-15T14:00:00Z' + organization_id: + description: Organization ID for the user's most recently active organization within this session. This represents the primary organization context for the current session. + type: string + examples: + - org_1234567890123456 + session_id: + description: Unique identifier for the session. System-generated read-only field used to reference this session. + type: string + examples: + - ses_1234567890123456 + status: + description: 'Current operational status of the session. Possible values: ''active'' (session is valid and requests are allowed), ''expired'' (session terminated due to idle or absolute timeout), ''revoked'' (session was administratively revoked), ''logout'' (user explicitly logged out). Use this to determine if the session can be used for new requests.' + type: string + examples: + - active + updated_at: + description: Timestamp indicating when the session was last updated. Updated whenever session state changes such as organization context changes or metadata updates. + type: string + format: date-time + examples: + - '2025-01-15T10:45:00Z' + user_id: + description: Unique identifier for the user who owns and is authenticated within this session. + type: string + examples: + - usr_1234567890123456 + sessionsRevokedSessionDetails: + type: object + properties: + absolute_expires_at: + description: The absolute expiration timestamp that was configured for this session before revocation. Represents the hard deadline regardless of activity. + type: string + format: date-time + examples: + - '2025-01-22T10:30:00Z' + created_at: + description: Timestamp indicating when the session was originally created before revocation. + type: string + format: date-time + examples: + - '2025-01-15T10:30:00Z' + expired_at: + description: Timestamp when the session was actually terminated. Set to the revocation time when the session is revoked. + type: string + format: date-time + examples: + - '2025-01-15T12:00:00Z' + idle_expires_at: + description: The idle expiration timestamp that was configured for this session before revocation. Represents when the session would have expired due to inactivity. + type: string + format: date-time + examples: + - '2025-01-15T11:30:00Z' + last_active_at: + description: Timestamp of the last recorded user activity in this session before revocation. Helps identify inactive sessions that were revoked. + type: string + format: date-time + examples: + - '2025-01-15T10:55:30Z' + logout_at: + description: Timestamp when the user explicitly logged out (if applicable). Null if the session was revoked without prior logout. + type: string + format: date-time + examples: + - '2025-01-15T14:00:00Z' + session_id: + description: Unique identifier for the revoked session. System-generated read-only field. + type: string + examples: + - ses_1234567890123456 + status: + description: Status of the session after revocation. Always 'revoked' since only active sessions can be revoked. Sessions that were already expired or logged out are not included in the revocation response. + type: string + examples: + - revoked + updated_at: + description: Timestamp indicating when the session was last modified before revocation. + type: string + format: date-time + examples: + - '2025-01-15T10:45:00Z' + user_id: + description: Unique identifier for the user who owned this session. + type: string + examples: + - usr_1234567890123456 + sessionsRevokeSessionResponse: + type: object + properties: + revoked_session: + description: Details of the revoked session including session ID, user ID, creation and revocation timestamps, and final device information. + $ref: '#/components/schemas/sessionsRevokedSessionDetails' + usersListUsersResponse: + type: object + properties: + next_page_token: + description: Token for retrieving the next page of results. Empty if there are no more pages. + type: string + examples: + - eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0= + prev_page_token: + description: Token for retrieving the previous page of results. Empty if this is the first page. + type: string + examples: + - eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9 + total_size: + description: Total number of users matching the request criteria, regardless of pagination. + type: integer + format: int64 + examples: + - 1042 + users: + description: List of users. + type: array + items: + type: object + $ref: '#/components/schemas/usersUser' + usersGetUserResponse: + type: object + properties: + user: + $ref: '#/components/schemas/usersUser' + usersUpdateUserProfile: + type: object + properties: + custom_attributes: + description: Updates custom attributes for extended user profile data and application-specific information. Use this field to store business-specific user data like department, job title, security clearances, project assignments, or any other organizational attributes your application requires. Unlike system metadata, these attributes are typically managed by administrators or applications and are visible to end users. Keys must be 3-25 characters, values must be 1-256 characters, with a maximum of 20 key-value pairs. + type: object + additionalProperties: + type: string + examples: + - department: engineering + security_clearance: level2 + family_name: + description: Updates the user's family name (last name or surname). Use this field to modify how the user's last name appears throughout the system. Maximum 255 characters allowed. + type: string + examples: + - Doe + first_name: + description: '[DEPRECATED] Use given_name instead. User''s given name. Maximum 200 characters.' + type: string + examples: + - John + gender: + description: Updates the user's gender identity information. Use this field to store the user's gender identity for personalization, compliance, or reporting purposes. This field supports any string value to accommodate diverse gender identities and should be handled with appropriate privacy considerations according to your organization's policies. + type: string + examples: + - male + given_name: + description: Updates the user's given name (first name). Use this field to modify how the user's first name appears in the system and user interfaces. Maximum 255 characters allowed. + type: string + examples: + - John + groups: + description: Updates the list of group names the user belongs to within the organization. Use this field to manage the user's group memberships for role-based access control, team assignments, or organizational structure. Groups are typically used for permission management and collaborative access. Each group name must be unique within the list, 1-250 characters long, with a maximum of 50 groups per user. + type: array + items: + type: string + examples: + - - engineering + - managers + last_name: + description: '[DEPRECATED] Use family_name instead. User''s family name. Maximum 200 characters.' + type: string + examples: + - Doe + locale: + description: Updates the user's preferred language and region settings using BCP-47 format codes. Use this field to customize the user's experience with localized content, date formats, number formatting, and UI language. When not specified, the user inherits the organization's default locale settings. Common values include `en-US`, `en-GB`, `fr-FR`, `de-DE`, and `es-ES`. + type: string + examples: + - en-US + metadata: + description: Updates system-managed key-value pairs for internal tracking and operational data. Use this field to store system-generated metadata like account status, signup source, last activity tracking, or integration-specific identifiers. These fields are typically managed by automated processes rather than direct user input. Keys must be 3-25 characters, values must be 1-256 characters, with a maximum of 20 key-value pairs. + type: object + additionalProperties: + type: string + examples: + - account_status: active + signup_source: mobile_app + name: + description: Updates the user's complete display name. Use this field when you want to set the full name as a single string rather than using separate given and family names. This name appears in user interfaces, reports, and anywhere a formatted display name is needed. + type: string + examples: + - John Doe + phone_number: + description: Updates the user's phone number in E.164 international format. Use this field to enable SMS-based authentication methods, two-factor authentication, or phone-based account recovery. The phone number must include the country code and be formatted according to E.164 standards (e.g., `+1` for US numbers). This field is required when enabling SMS authentication features. + type: string + examples: + - '+14155552671' + picture: + description: Updates the URL to the user's profile picture or avatar image. Use this field to set or change the user's profile photo that appears in user interfaces, directory listings, and collaborative features. The URL should point to a publicly accessible image file. Supported formats typically include JPEG, PNG, and GIF. Maximum URL length is 2048 characters. + type: string + examples: + - https://example.com/avatar.jpg + preferred_username: + description: Updates the user's preferred username for display and identification purposes. Use this field to set a custom username that the user prefers to be known by, which may differ from their email or formal name. This username appears in user interfaces, mentions, and informal communications. Maximum 512 characters allowed. + type: string + examples: + - John Michael Doe + v1usersUpdateUser: + type: object + properties: + external_id: + description: Your application's unique identifier for this organization, used to link Scalekit with your system. + type: string + examples: + - ext_12345a67b89c + metadata: + description: Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars). + type: object + additionalProperties: + type: string + examples: + - department: engineering + location: nyc-office + user_profile: + description: User's personal information including name, address, and other profile attributes. + $ref: '#/components/schemas/usersUpdateUserProfile' + usersUpdateUserResponse: + type: object + properties: + user: + $ref: '#/components/schemas/usersUser' + sessionsUserSessionDetails: + type: object + properties: + next_page_token: + description: Pagination token for retrieving the next page of results. Empty string if there are no more pages (you have reached the final page of results). + type: string + examples: + - eyJwYWdlIjogMiwgImxhc3RfaWQiOiAic2VzXzEyMzQ1In0= + prev_page_token: + description: Pagination token for retrieving the previous page of results. Empty string for the first page. Use this to navigate backward through result pages. + type: string + examples: + - eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInNlc183OTAxIn0= + sessions: + description: Array of session objects for the requested user. May contain fewer entries than the requested page_size when reaching the final page of results. + type: array + items: + type: object + $ref: '#/components/schemas/sessionsSessionDetails' + total_size: + description: Total number of sessions matching the applied filter criteria, regardless of pagination. This represents the complete result set size before pagination is applied. + type: integer + format: int64 + examples: + - 42 + sessionsRevokeAllUserSessionsResponse: + type: object + properties: + revoked_sessions: + description: List of all sessions that were revoked, including detailed information for each revoked session with IDs, timestamps, and device details. + type: array + items: + type: object + $ref: '#/components/schemas/sessionsRevokedSessionDetails' + total_revoked: + description: Total count of active sessions that were revoked. Useful for confirmation and audit logging. + type: integer + format: int64 + examples: + - 5 + usersSearchUsersResponse: + type: object + properties: + next_page_token: + description: Token for retrieving the next page of results. Empty if there are no more pages. + type: string + examples: + - eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0= + prev_page_token: + description: Token for retrieving the previous page of results. Empty if this is the first page. + type: string + examples: + - eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9 + total_size: + description: Total number of users matching the request criteria, regardless of pagination. + type: integer + format: int64 + examples: + - 1042 + users: + description: List of matching users. + type: array + items: + type: object + $ref: '#/components/schemas/usersUser' + webauthnAllAcceptedCredentialsOptions: + type: object + properties: + all_accepted_credential_ids: + description: List of credential IDs the user can authenticate with + type: array + items: + type: string + rp_id: + description: Relying Party ID for credential operations + type: string + examples: + - example.com + user_id: + description: User ID for credential verification + type: string + examples: + - user_xyz789 + WebAuthnCredentialAuthenticator: + type: object + properties: + aaguid: + description: Authenticator Attestation GUID (AAGUID) identifying the device model + type: string + attachment: + description: 'Attachment type: "platform" (built-in) or "cross-platform"' + type: string + examples: + - platform + icon_dark: + description: Icon URL for dark theme display + type: string + icon_light: + description: Icon URL for light theme display + type: string + name: + description: Human-readable name of the authenticator model + type: string + examples: + - Apple Touch ID + WebAuthnCredentialAuthenticatorFlags: + type: object + properties: + backup_eligible: + description: Whether this credential can be backed up to another device + type: boolean + backup_state: + description: Whether this credential was synced or backed up + type: boolean + user_present: + description: Whether the user was present during authentication + type: boolean + user_verified: + description: Whether the user was verified (e.g., fingerprint, PIN) + type: boolean + WebAuthnCredentialClientInfo: + type: object + properties: + city: + description: City name + type: string + examples: + - San Francisco + ip: + description: IP address from which credential was registered + type: string + examples: + - 192.0.2.1 + region: + description: Geographic region (e.g., "US") + type: string + examples: + - US + region_subdivision: + description: Regional subdivision (e.g., "CA") + type: string + examples: + - CA + WebAuthnCredentialUserAgent: + type: object + properties: + browser: + description: Browser name (e.g., "Chrome", "Safari") + type: string + examples: + - Chrome + browser_version: + description: Browser version number + type: string + examples: + - 120.0.6099.129 + device_model: + description: Device model if available + type: string + examples: + - iPhone15,2 + device_type: + description: 'Device type: "desktop", "mobile", or "tablet"' + type: string + examples: + - mobile + os: + description: Operating system name (e.g., "Windows", "iOS") + type: string + examples: + - macOS + os_version: + description: Operating system version + type: string + examples: + - '14.2' + raw: + description: Raw user agent string from the browser + type: string + url: + description: Parsed user agent URL reference + type: string + webauthnWebAuthnCredential: + type: object + properties: + attestation_type: + description: 'Type of attestation: "none", "indirect", or "direct"' + type: string + examples: + - direct + authenticator: + description: Authenticator information including model and name + $ref: '#/components/schemas/WebAuthnCredentialAuthenticator' + authenticator_flags: + description: Flags indicating authenticator capabilities + $ref: '#/components/schemas/WebAuthnCredentialAuthenticatorFlags' + client_info: + description: Geographic and network information from registration + $ref: '#/components/schemas/WebAuthnCredentialClientInfo' + created_at: + description: Timestamp when the credential was created + type: string + format: date-time + examples: + - '2025-02-15T06:23:44.560000Z' + credential_id: + description: The actual credential ID bytes from the authenticator + type: string + contentEncoding: base64 + display_name: + description: Optional user-friendly name for this passkey + type: string + examples: + - My Yubikey + id: + description: Credential unique identifier + type: string + examples: + - cred_abc123 + transports: + description: Supported transports for this credential + type: array + items: + type: string + updated_at: + description: Timestamp of last update + type: string + format: date-time + examples: + - '2025-02-15T06:23:44.560000Z' + user_agent: + description: Browser and device information from registration + $ref: '#/components/schemas/WebAuthnCredentialUserAgent' + user_id: + description: User ID this credential belongs to + type: string + examples: + - user_xyz789 + webauthnListCredentialsResponse: + type: object + properties: + all_accepted_credentials_options: + description: Options including RP ID and all accepted credential IDs for authentication + $ref: '#/components/schemas/webauthnAllAcceptedCredentialsOptions' + credentials: + description: All passkeys registered for the user + type: array + items: + type: object + $ref: '#/components/schemas/webauthnWebAuthnCredential' + webauthnUnknownCredentialOptions: + type: object + properties: + credential_id: + description: The deleted credential ID + type: string + examples: + - cred_abc123 + rp_id: + description: The RP ID for this credential + type: string + examples: + - example.com + webauthnDeleteCredentialResponse: + type: object + properties: + success: + description: Whether the credential was successfully deleted + type: boolean + examples: + - true + unknown_credential_options: + description: Options for handling unknown credentials in client applications + $ref: '#/components/schemas/webauthnUnknownCredentialOptions' + WebAuthnServiceUpdateCredentialBody: + type: object + properties: + display_name: + description: Human-friendly name for this credential (1-120 characters) + type: string + examples: + - My iPhone 15 Pro + webauthnUpdateCredentialResponse: + type: object + properties: + credential: + description: The updated credential with new display name + $ref: '#/components/schemas/webauthnWebAuthnCredential' + ScalekitEvent: + type: object + required: + - spec_version + - id + - type + - occurred_at + - environment_id + - object + properties: + spec_version: + type: string + example: '1' + description: The webhook specification version + pattern: ^[0-9]+$ + id: + type: string + pattern: ^evt_ + example: evt_1234567890abcdef + description: Unique identifier for the webhook event (must be prefixed with "evt_") + minLength: 1 + maxLength: 32 + type: + type: string + example: organization.created + description: The event type + enum: + - organization.created + - organization.updated + - organization.deleted + - organization.sso_created + - organization.sso_deleted + - organization.sso_enabled + - organization.sso_disabled + - user.signup + - user.login + - user.logout + - user.organization_invitation + - user.organization_membership_created + - user.organization_membership_updated + - user.organization_membership_deleted + - organization.directory.user_created + - organization.directory.user_updated + - organization.directory.user_deleted + - organization.directory.group_created + - organization.directory.group_updated + - organization.directory.group_deleted + - organization.directory_enabled + - organization.directory_disabled + - role.created + - role.updated + - role.deleted + - permission.created + - permission.updated + - permission.deleted + occurred_at: + type: string + format: date-time + description: When the event occurred (ISO 8601 format) + example: '2024-01-01T00:00:00Z' + environment_id: + type: string + pattern: ^env_ + example: env_1234567890abcdef + description: The environment ID where the event occurred + minLength: 1 + maxLength: 32 + organization_id: + type: string + pattern: ^org_ + example: org_1234567890abcdef + description: The organization ID (if applicable) + minLength: 1 + maxLength: 32 + object: + type: string + description: The type of object that triggered the webhook + enum: + - Organization + - Connection + - Role + - Directory + - DirectoryUser + - DirectoryGroup + - Permission + - OrgMembership + - User + example: Organization + data: + type: object + description: The event payload (structure varies by event type) + additionalProperties: true + example: + id: org_1234567890abcdef + name: Example Organization + created_at: '2024-01-01T00:00:00Z' + display_name: + type: string + description: Human-readable display name for the event + example: Organization Created + minLength: 1 + maxLength: 200 +x-scalar-environments: + production: + variables: + SCALEKIT_ENVIRONMENT_URL: + default: https://$SCALEKIT_ENVIRONMENT_URL + description: yourapp.scalekit.com + staging: + variables: + SCALEKIT_ENVIRONMENT_URL: + default: https://$SCALEKIT_ENVIRONMENT_URL + description: yourapp.scalekit.dev +x-scalar-active-environment: staging diff --git a/redocly.yaml b/redocly.yaml new file mode 100644 index 000000000..cfdd94f7f --- /dev/null +++ b/redocly.yaml @@ -0,0 +1,8 @@ +apis: + agentkit: + root: openapi/agentkit.yaml + output: public/api/agentkit.scalar.yaml + + saaskit: + root: openapi/saaskit.yaml + output: public/api/saaskit.scalar.yaml \ No newline at end of file diff --git a/src/configs/secondary-nav.config.ts b/src/configs/secondary-nav.config.ts index aec5d0401..4c5d7a749 100644 --- a/src/configs/secondary-nav.config.ts +++ b/src/configs/secondary-nav.config.ts @@ -54,7 +54,7 @@ const sharedSdksItem: NavItem = { }, { id: 'rest-apis', - href: '/apis/#description/overview', + href: '/saaskit/apis/', label: 'REST APIs', iconComponent: IconApi, description: 'Programmatic control to manage users, orgs, sessions etc.', @@ -83,7 +83,7 @@ const agentKitItems: NavItem[] = [ }, { id: 'agentkit-api-reference', - href: '/apis/?product=agentkit', + href: '/agentkit/apis/', label: 'API reference', iconComponent: IconApi, }, diff --git a/src/configs/sidebar.config.ts b/src/configs/sidebar.config.ts index ced0f909f..cb1bdfc82 100644 --- a/src/configs/sidebar.config.ts +++ b/src/configs/sidebar.config.ts @@ -666,6 +666,7 @@ export const sidebarToSecondaryNav: Record = { '/agentkit/connections': 'agentkit-quickstart', '/agentkit/connected-accounts': 'agentkit-connectors', '/agentkit/sdks': 'agentkit-sdks', + '/agentkit/apis': 'agentkit-api-reference', '/agentkit/tools/agent-tools-quickstart': 'agentkit-quickstart', '/agentkit/openclaw': 'agentkit-quickstart', '/agentkit/frameworks': 'agentkit-quickstart', diff --git a/src/pages/agentkit/apis.astro b/src/pages/agentkit/apis.astro new file mode 100644 index 000000000..53a14537b --- /dev/null +++ b/src/pages/agentkit/apis.astro @@ -0,0 +1,250 @@ +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro' +import { ScalarComponent } from '@scalar/astro' + +const template = 'splash' as const +const frontmatter = { + title: 'AgentKit API Reference', + description: 'API reference for Scalekit AgentKit — connected accounts and agent authentication', + template, + editUrl: false as const, + head: [ + { + tag: 'style' as const, + content: ` + footer { + display: none !important; + } + .content-panel:first-of-type:has(.sl-container:empty), + .content-panel:first-of-type:not(:has(.api-reference-wrapper)) { + display: none !important; + } + .content-panel:first-of-type:empty { + display: none !important; + } + .content-panel { + border-top: none !important; + } + .footer-fold-separator { + display: none !important; + } + .scalar-api-reference { + position: sticky; + top: var(--sl-nav-height); + height: calc(100vh - var(--sl-nav-height)); + overflow: auto; + } + :root { + --sl-content-width: 100%; + } + `, + }, + ], +} +--- + +
+ + + { + const tagOrder = ['Connected Accounts'] + const getTagRank = (name) => { + const rank = tagOrder.indexOf(name ?? '') + return rank === -1 ? Number.POSITIVE_INFINITY : rank + } + const rankA = getTagRank(a?.name) + const rankB = getTagRank(b?.name) + + if (rankA !== rankB) { + return rankA - rankB + } + + return (a?.name ?? '').localeCompare(b?.name ?? '') + }, + operationsSorter: (a, b) => { + const methodOrder = ['get', 'post', 'put', 'patch', 'delete'] + const getMethodRank = (method) => { + const rank = methodOrder.indexOf((method ?? '').toLowerCase()) + return rank === -1 ? Number.POSITIVE_INFINITY : rank + } + const methodComparison = getMethodRank(a?.method) - getMethodRank(b?.method) + + if (methodComparison !== 0) { + return methodComparison + } + + return (a?.path ?? '').localeCompare(b?.path ?? '') + }, + servers: [ + { + url: 'https://{SCALEKIT_ENVIRONMENT_URL}', + description: 'Scalekit Environment', + variables: { + SCALEKIT_ENVIRONMENT_URL: { + default: 'your-env.scalekit.com', + description: + 'Your full Scalekit environment URL (e.g., my-env.scalekit.com or my-env.scalekit.dev)', + }, + }, + }, + ], + authentication: { + preferredSecurityScheme: 'oauth2', + securitySchemes: { + oauth2: { + type: 'oauth2', + flows: { + clientCredentials: { + tokenUrl: 'https://{SCALEKIT_ENVIRONMENT_URL}/oauth/token', + 'x-scalar-credentials-location': 'body', + 'x-scalar-security-body': { + grant_type: 'client_credentials', + }, + }, + }, + }, + }, + }, + hiddenClients: { + c: ['libcurl'], + csharp: ['httpclient', 'restsharp'], + clojure: ['clj_http'], + dart: ['http'], + go: ['native'], + http: ['http1.1', 'http1', 'http2'], + java: ['asynchttp', 'okhttp', 'unirest', 'nethttp'], + js: ['xhr', 'fetch', 'axios', 'jquery', 'ofetch', 'request'], + kotlin: ['okhttp'], + node: ['undici', 'axios', 'fetch', 'ofetch'], + objc: ['nsurlsession'], + ocaml: ['cohttp'], + fsharp: ['httpclient'], + php: ['curl', 'guzzle'], + powershell: ['restmethod', 'webrequest'], + python: ['python3', 'requests', 'httpx_sync', 'httpx_async'], + r: ['httr'], + ruby: ['native'], + rust: ['reqwest'], + shell: ['httpie', 'wget'], + swift: ['nsurlsession'], + }, + favicon: + 'https://cdn.prod.website-files.com/65b87d98fa638289e10b8f61/67ab35acf2f180e0fe0a94a8_S%20Icon%20-%20Black%20-%2032x32.png', + hideClientButton: true, + baseServerURL: 'https://scalekit.com', + documentDownloadType: 'json', + customCss: ` + #scalar-client-0 { margin-top: 8rem; } + .introduction-card-item.scalar-reference-intro-clients { display: none; } + `, + generateWebhookSlug: (webhook) => { + const name = webhook.name || webhook.summary || 'list-of-events' + + return name + .toLowerCase() + .replace(/[^a-z0-9\s-]/g, '') + .replace(/\s+/g, '-') + .replace(/-+/g, '-') + .replace(/^-|-$/g, '') + }, + }} + /> +
+ + + \ No newline at end of file diff --git a/src/pages/saaskit/apis.astro b/src/pages/saaskit/apis.astro new file mode 100644 index 000000000..4f69f90c7 --- /dev/null +++ b/src/pages/saaskit/apis.astro @@ -0,0 +1,262 @@ +--- +import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro' +import { ScalarComponent } from '@scalar/astro' + +const template = 'splash' as const +const frontmatter = { + title: 'SaaSKit API Reference', + description: 'API reference for Scalekit SaaSKit — SSO, SCIM, directories, sessions, and more', + template, + editUrl: false as const, + head: [ + { + tag: 'style' as const, + content: ` + footer { + display: none !important; + } + .content-panel:first-of-type:has(.sl-container:empty), + .content-panel:first-of-type:not(:has(.api-reference-wrapper)) { + display: none !important; + } + .content-panel:first-of-type:empty { + display: none !important; + } + .content-panel { + border-top: none !important; + } + .footer-fold-separator { + display: none !important; + } + .scalar-api-reference { + position: sticky; + top: var(--sl-nav-height); + height: calc(100vh - var(--sl-nav-height)); + overflow: auto; + } + :root { + --sl-content-width: 100%; + } + `, + }, + ], +} +--- + +
+ + + { + const tagOrder = [ + 'Organizations', + 'Permissions', + 'Users', + 'Connections', + 'Directory', + 'Roles', + 'Sessions', + 'Domains', + 'API Auth', + 'Magic link & OTP', + 'Passkeys', + ] + const getTagRank = (name) => { + const rank = tagOrder.indexOf(name ?? '') + return rank === -1 ? Number.POSITIVE_INFINITY : rank + } + const rankA = getTagRank(a?.name) + const rankB = getTagRank(b?.name) + + if (rankA !== rankB) { + return rankA - rankB + } + + return (a?.name ?? '').localeCompare(b?.name ?? '') + }, + operationsSorter: (a, b) => { + const methodOrder = ['get', 'post', 'put', 'patch', 'delete'] + const getMethodRank = (method) => { + const rank = methodOrder.indexOf((method ?? '').toLowerCase()) + return rank === -1 ? Number.POSITIVE_INFINITY : rank + } + const methodComparison = getMethodRank(a?.method) - getMethodRank(b?.method) + + if (methodComparison !== 0) { + return methodComparison + } + + return (a?.path ?? '').localeCompare(b?.path ?? '') + }, + servers: [ + { + url: 'https://{SCALEKIT_ENVIRONMENT_URL}', + description: 'Scalekit Environment', + variables: { + SCALEKIT_ENVIRONMENT_URL: { + default: 'your-env.scalekit.com', + description: + 'Your full Scalekit environment URL (e.g., my-env.scalekit.com or my-env.scalekit.dev)', + }, + }, + }, + ], + authentication: { + preferredSecurityScheme: 'oauth2', + securitySchemes: { + oauth2: { + type: 'oauth2', + flows: { + clientCredentials: { + tokenUrl: 'https://{SCALEKIT_ENVIRONMENT_URL}/oauth/token', + 'x-scalar-credentials-location': 'body', + 'x-scalar-security-body': { + grant_type: 'client_credentials', + }, + }, + }, + }, + }, + }, + hiddenClients: { + c: ['libcurl'], + csharp: ['httpclient', 'restsharp'], + clojure: ['clj_http'], + dart: ['http'], + go: ['native'], + http: ['http1.1', 'http1', 'http2'], + java: ['asynchttp', 'okhttp', 'unirest', 'nethttp'], + js: ['xhr', 'fetch', 'axios', 'jquery', 'ofetch', 'request'], + kotlin: ['okhttp'], + node: ['undici', 'axios', 'fetch', 'ofetch'], + objc: ['nsurlsession'], + ocaml: ['cohttp'], + fsharp: ['httpclient'], + php: ['curl', 'guzzle'], + powershell: ['restmethod', 'webrequest'], + python: ['python3', 'requests', 'httpx_sync', 'httpx_async'], + r: ['httr'], + ruby: ['native'], + rust: ['reqwest'], + shell: ['httpie', 'wget'], + swift: ['nsurlsession'], + }, + favicon: + 'https://cdn.prod.website-files.com/65b87d98fa638289e10b8f61/67ab35acf2f180e0fe0a94a8_S%20Icon%20-%20Black%20-%2032x32.png', + hideClientButton: true, + baseServerURL: 'https://scalekit.com', + documentDownloadType: 'json', + customCss: ` + #scalar-client-0 { margin-top: 8rem; } + .introduction-card-item.scalar-reference-intro-clients { display: none; } + `, + generateWebhookSlug: (webhook) => { + const name = webhook.name || webhook.summary || 'list-of-events' + + return name + .toLowerCase() + .replace(/[^a-z0-9\s-]/g, '') + .replace(/\s+/g, '-') + .replace(/-+/g, '-') + .replace(/^-|-$/g, '') + }, + }} + /> +
+ + + \ No newline at end of file diff --git a/src/utils/secondary-nav-utils.ts b/src/utils/secondary-nav-utils.ts index 6470e67a0..103c66fde 100644 --- a/src/utils/secondary-nav-utils.ts +++ b/src/utils/secondary-nav-utils.ts @@ -91,11 +91,9 @@ export function getActiveSecondaryNavId( } // 3. Hard-coded fallbacks for pages without a sidebar (e.g. Scalar /apis) - if (pathname.startsWith('/apis')) { - // When arriving from AgentKit context, highlight the AgentKit API reference item - if (searchParams?.get('product') === 'agentkit') return 'agentkit-api-reference' - return 'rest-apis' - } + if (pathname.startsWith('/agentkit/apis')) return 'agentkit-api-reference' + if (pathname.startsWith('/saaskit/apis')) return 'rest-apis' + if (pathname.startsWith('/apis')) return 'rest-apis' // Fallback for AgentKit pages not registered in the sidebar map (e.g. /agentkit/sdks index) // Routes through the 'connect' mapping which has path overrides for all /agentkit/* paths. From 35a6717ebd5f93000a1280addf3de6af99644393 Mon Sep 17 00:00:00 2001 From: Saif Ali Shaik Date: Tue, 19 May 2026 17:14:42 +0530 Subject: [PATCH 02/28] Add bundled JSON specs and updated d2 diagrams --- public/api/agentkit.scalar.json | 1834 +++ public/api/saaskit.scalar.json | 12042 ++++++++++++++++ .../litellm-agentkit-inbox-triage-0.svg | 2 +- .../litellm-agentkit-inbox-triage-1.svg | 2 +- 4 files changed, 13878 insertions(+), 2 deletions(-) create mode 100644 public/api/agentkit.scalar.json create mode 100644 public/api/saaskit.scalar.json diff --git a/public/api/agentkit.scalar.json b/public/api/agentkit.scalar.json new file mode 100644 index 000000000..b94e3407e --- /dev/null +++ b/public/api/agentkit.scalar.json @@ -0,0 +1,1834 @@ +{ + "openapi": "3.1.1", + "info": { + "description": "The AgentKit API enables you to manage connected accounts for third-party integrations, execute tools on behalf of users, and handle OAuth connections to external services like Google, Notion, Slack, and other applications.\n\n## Quickstart\n\nThe Scalekit API uses OAuth 2.0 Client Credentials for authentication.\n\nCopy your API credentials from the Scalekit dashboard's API Config section and set them as environment variables.\n\n```sh\nSCALEKIT_ENVIRONMENT_URL=''\nSCALEKIT_CLIENT_ID=''\nSCALEKIT_CLIENT_SECRET=''\n```\n\nGetting an access token\n\n1. Get your credentials from the [Scalekit Dashboard](https://app.scalekit.com)\n2. Request an access token:\n\n```sh\ncurl https:///oauth/token \\\n -X POST \\\n -H 'Content-Type: application/x-www-form-urlencoded' \\\n -d 'client_id={client_id}' \\\n -d 'client_secret={client_secret}' \\\n -d 'grant_type=client_credentials'\n```\n\n3. Use the access token in API requests:\n\n```sh\ncurl https:///api/v1/connected_accounts \\\n -H 'Content-Type: application/json' \\\n -H 'Authorization: Bearer {access_token}'\n```\n", + "title": "AgentKit APIs", + "contact": { + "name": "Scalekit Inc", + "url": "https://scalekit.com", + "email": "support@scalekit.com" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + }, + "version": "1.0.0" + }, + "servers": [ + { + "url": "https://$SCALEKIT_ENVIRONMENT_URL" + } + ], + "security": [ + { + "oauth2": [] + } + ], + "tags": [ + { + "description": "Manage connected accounts for third-party integrations and OAuth connections. Connected accounts represent authenticated access to external services like Google, Notion, Slack, and other applications.", + "name": "Connected Accounts" + } + ], + "externalDocs": { + "description": "Scalekit Docs", + "url": "https://docs.scalekit.com/" + }, + "paths": { + "/api/v1/connected_accounts": { + "get": { + "description": "Retrieves a paginated list of connected accounts for third-party integrations. Filter by organization, user, connector type, provider, or identifier. Returns OAuth tokens, API keys, and connection status for each account. Use pagination tokens to navigate through large result sets.", + "tags": [ + "Connected Accounts" + ], + "summary": "List connected accounts", + "operationId": "ConnectedAccountService_ListConnectedAccounts", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Filter by organization ID. Returns only connected accounts associated with this organization.", + "name": "organization_id", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Filter by user ID. Returns only connected accounts associated with this user.", + "name": "user_id", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Filter by connector type. Connector identifier such as 'notion', 'slack', 'google', etc. Alphanumeric with spaces, hyphens, underscores, and colons allowed.", + "name": "connector", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Filter by account identifier. The unique identifier for the connected account within the third-party service (e.g., email address, workspace ID).", + "name": "identifier", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Filter by OAuth provider. The authentication provider name such as 'google', 'microsoft', 'github', etc.", + "name": "provider", + "in": "query" + }, + { + "schema": { + "type": "integer", + "format": "int64" + }, + "description": "Maximum number of connected accounts to return per page. Must be between 0 and 100. Default is typically 10.", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Pagination token from a previous response. Use the next_page_token value from ListConnectedAccountsResponse to fetch the next page.", + "name": "page_token", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Text search query to filter connected accounts by name, identifier, or other searchable fields. Case-insensitive.", + "name": "query", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of connected accounts with their authentication details and status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsListConnectedAccountsResponse" + } + } + } + }, + "400": { + "description": "Invalid request - occurs when query parameters are malformed or validation fails", + "content": { + "application/json": { + "schema": {} + } + } + }, + "401": { + "description": "Authentication required - missing or invalid access token", + "content": { + "application/json": { + "schema": {} + } + } + } + } + }, + "put": { + "description": "Updates authentication credentials and configuration for an existing connected account. Modify OAuth tokens, refresh tokens, access scopes, or API configuration settings. Specify the account by ID, or by combination of organization/user, connector, and identifier. Returns the updated account with new token expiry and status information.", + "tags": [ + "Connected Accounts" + ], + "summary": "Update connected account credentials", + "operationId": "ConnectedAccountService_UpdateConnectedAccount", + "responses": { + "200": { + "description": "Connected account updated successfully with new credentials or configuration", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsUpdateConnectedAccountResponse" + } + } + } + }, + "400": { + "description": "Invalid request - missing required fields, invalid authorization details, or validation failed", + "content": { + "application/json": { + "schema": {} + } + } + }, + "401": { + "description": "Authentication required - missing or invalid access token", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Connected account not found - the specified account does not exist", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsUpdateConnectedAccountRequest" + } + } + }, + "required": true + } + }, + "post": { + "description": "Creates a new connected account with OAuth tokens or API credentials for third-party service integration. Supply authorization details including access tokens, refresh tokens, scopes, and optional API configuration. The account can be scoped to an organization or user. Returns the created account with its unique identifier and authentication status.", + "tags": [ + "Connected Accounts" + ], + "summary": "Create a connected account", + "operationId": "ConnectedAccountService_CreateConnectedAccount", + "responses": { + "201": { + "description": "Connected account created successfully with authentication credentials stored securely", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsCreateConnectedAccountResponse" + } + } + } + }, + "400": { + "description": "Invalid request - missing required fields, invalid authorization details, or validation failed", + "content": { + "application/json": { + "schema": {} + } + } + }, + "401": { + "description": "Authentication required - missing or invalid access token", + "content": { + "application/json": { + "schema": {} + } + } + }, + "409": { + "description": "Conflict - connected account with the same identifier already exists", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsCreateConnectedAccountRequest" + } + } + }, + "required": true + } + } + }, + "/api/v1/connected_accounts/auth": { + "get": { + "description": "Retrieves complete authentication details for a connected account including OAuth tokens, refresh tokens, scopes, and API configuration. Query by account ID or by combination of organization/user, connector, and identifier. Returns sensitive credential information - use appropriate access controls.", + "tags": [ + "Connected Accounts" + ], + "summary": "Get connected account details", + "operationId": "ConnectedAccountService_GetConnectedAccountAuth", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Organization ID for the connector", + "name": "organization_id", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "User ID for the connector", + "name": "user_id", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Connector identifier", + "name": "connector", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).", + "name": "identifier", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the connected account", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved connected account with full authentication details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsGetConnectedAccountByIdentifierResponse" + } + } + } + }, + "400": { + "description": "Invalid request - missing required query parameters", + "content": { + "application/json": { + "schema": {} + } + } + }, + "401": { + "description": "Authentication required - missing or invalid access token", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Connected account not found - no account matches the specified criteria", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, + "/api/v1/connected_accounts/magic_link": { + "post": { + "description": "Creates a time-limited magic link for connecting or re-authorizing a third-party account. The link directs users to the OAuth authorization flow for the specified connector. Returns the generated link URL and expiration timestamp. Links typically expire after a short duration for security.", + "tags": [ + "Connected Accounts" + ], + "summary": "Generate authentication magic link", + "operationId": "ConnectedAccountService_GetMagicLinkForConnectedAccount", + "responses": { + "200": { + "description": "Magic link generated successfully with authorization URL and expiry time", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsGetMagicLinkForConnectedAccountResponse" + } + } + } + }, + "400": { + "description": "Invalid request - missing required parameters or invalid connector", + "content": { + "application/json": { + "schema": {} + } + } + }, + "401": { + "description": "Authentication required - missing or invalid access token", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsGetMagicLinkForConnectedAccountRequest" + } + } + }, + "required": true + } + } + }, + "/api/v1/connected_accounts/user/verify": { + "post": { + "description": "Confirms the user assertion and activates the connected account after the user completes third-party OAuth. Called by the B2B app server with auth_request_id and identifier. Validates that the asserted identifier matches the one stored on the auth request and promotes pending tokens to live.", + "tags": [ + "Connected Accounts" + ], + "summary": "Verify connected account user", + "operationId": "ConnectedAccountService_VerifyConnectedAccountUser", + "responses": { + "200": { + "description": "Verification successful; connected account is now ACTIVE", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsVerifyConnectedAccountUserResponse" + } + } + } + }, + "400": { + "description": "Invalid request - missing or malformed fields", + "content": { + "application/json": { + "schema": {} + } + } + }, + "401": { + "description": "Unauthorized - invalid or missing access token", + "content": { + "application/json": { + "schema": {} + } + } + }, + "403": { + "description": "Forbidden - identifier mismatch", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Not found - no pending flow for the given auth_request_id or already consumed", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsVerifyConnectedAccountUserRequest" + } + } + }, + "required": true + } + } + }, + "/api/v1/connected_accounts:delete": { + "post": { + "description": "Permanently removes a connected account and revokes all associated authentication credentials. Identify the account by ID, or by combination of organization/user, connector, and identifier. This action cannot be undone. All OAuth tokens and API keys for this account will be invalidated.", + "tags": [ + "Connected Accounts" + ], + "summary": "Delete a connected account", + "operationId": "ConnectedAccountService_DeleteConnectedAccount", + "responses": { + "200": { + "description": "Connected account deleted successfully and all credentials revoked", + "content": { + "application/json": { + "schema": {} + } + } + }, + "400": { + "description": "Invalid request - malformed parameters or validation failed", + "content": { + "application/json": { + "schema": {} + } + } + }, + "401": { + "description": "Authentication required - missing or invalid access token", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Connected account not found - the specified account does not exist", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsDeleteConnectedAccountRequest" + } + } + }, + "required": true + } + } + }, + "/api/v1/connected_accounts:search": { + "get": { + "description": "Search for connected accounts in your environment using a text query that matches against identifiers, providers, or connectors. The search performs case-insensitive matching across account details. Returns paginated results with account status and authentication type information.", + "tags": [ + "Connected Accounts" + ], + "summary": "Search connected accounts", + "operationId": "ConnectedAccountService_SearchConnectedAccounts", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Search term to match against connected account identifiers, providers, or connectors. Must be at least 3 characters. Case insensitive.", + "name": "query", + "in": "query" + }, + { + "schema": { + "type": "integer", + "format": "int64" + }, + "description": "Maximum number of connected accounts to return per page. Value must be between 1 and 30.", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Token from a previous response for pagination. Provide this to retrieve the next page of results.", + "name": "page_token", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Connection ID to filter connected accounts", + "name": "connection_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved matching connected accounts with pagination support", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connected_accountsSearchConnectedAccountsResponse" + } + } + } + }, + "400": { + "description": "Invalid request - query parameter is too short (minimum 3 characters) or validation failed", + "content": { + "application/json": { + "schema": {} + } + } + }, + "401": { + "description": "Authentication required - missing or invalid access token", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, + "/api/v1/execute_tool": { + "post": { + "description": "Executes a tool action using authentication credentials from a connected account. Specify the tool by name and provide required parameters as JSON. The connected account can be identified by ID, or by combination of organization/user, connector, and identifier. Returns the execution result data and a unique execution ID for tracking. Use this endpoint to perform actions like sending emails, creating calendar events, or managing resources in external services.", + "tags": [ + "Connected Accounts" + ], + "summary": "Execute a tool using a connected account", + "operationId": "ToolService_ExecuteTool", + "responses": { + "200": { + "description": "Tool executed successfully with result data and execution ID", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/toolsExecuteToolResponse" + } + } + } + }, + "400": { + "description": "Invalid request - occurs when tool name is missing, parameters are malformed, or tool definition validation fails", + "content": { + "application/json": { + "schema": {} + } + } + }, + "401": { + "description": "Authentication required - missing or invalid access token", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Tool or connected account not found - occurs when the specified tool name or connected account does not exist", + "content": { + "application/json": { + "schema": {} + } + } + }, + "500": { + "description": "Tool execution failed - occurs when the external service returns an error or the tool encounters a runtime exception", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/toolsExecuteToolRequest" + } + } + }, + "required": true + } + } + } + }, + "webhooks": { + "connected_account.created": { + "post": { + "summary": "Connected Account Created", + "description": "Triggered when a new connected account is created", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_101531404017336586", + "type": "connected_account.created", + "object": "ConnectedAccount", + "occurred_at": "2025-12-01T10:23:52.702980847Z", + "environment_id": "env_88640229614813449", + "data": { + "authorization_type": "OAUTH", + "connection_id": "conn_100668583155073286", + "id": "ca_101531404000559370", + "identifier": "Bruce", + "provider": "CANVA", + "status": "PENDING_AUTH" + } + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "connected_account.updated": { + "post": { + "summary": "Connected Account Updated", + "description": "Triggered when a connected account is updated", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_101652975398683158", + "type": "connected_account.updated", + "object": "ConnectedAccount", + "occurred_at": "2025-12-02T06:31:34.895815554Z", + "environment_id": "env_88640229614813449", + "display_name": "Connected account updated", + "data": { + "authorization_type": "OAUTH", + "connection_id": "conn_100510054016352776", + "id": "ca_100510623602835982", + "identifier": "Pranesh", + "provider": "SUPABASE", + "status": "PENDING_AUTH" + } + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "connected_account.deleted": { + "post": { + "summary": "Connected Account Deleted", + "description": "Triggered when a connected account is deleted", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_101653010731500290", + "type": "connected_account.deleted", + "object": "ConnectedAccount", + "occurred_at": "2025-12-02T06:31:55.954027187Z", + "environment_id": "env_88640229614813449", + "display_name": "connected account deleted", + "data": { + "authorization_type": "OAUTH", + "connection_id": "conn_101644109747323155", + "id": "ca_101649788113519113", + "identifier": "Clark", + "last_used_at": "2025-12-02T06:00:01.374253Z", + "provider": "GOOGLE_ADS", + "status": "ACTIVE", + "token_expires_at": "2025-12-02T06:59:57.237447Z" + } + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "connected_account.magic_link_generated": { + "post": { + "summary": "Connected Account Magic Link Generated", + "description": "Triggered when a magic link is generated for OAuth flow", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_101652975398683158", + "type": "connected_account.magic_link_generated", + "object": "ConnectedAccount", + "occurred_at": "2025-12-02T06:31:34.895815554Z", + "environment_id": "env_88640229614813448", + "data": { + "authorization_type": "OAUTH", + "connection_id": "conn_100510054016352776", + "id": "ca_100510623602835982", + "identifier": "Pranesh", + "provider": "SUPABASE", + "status": "PENDING_AUTH" + } + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "connected_account.oauth_tokens_fetched": { + "post": { + "summary": "Connected Account OAuth Tokens Fetched", + "description": "Triggered when OAuth tokens are successfully fetched", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_101649795042509316", + "type": "connected_account.oauth_tokens_fetched", + "object": "ConnectedAccount", + "occurred_at": "2025-12-02T05:59:59.250126407Z", + "environment_id": "env_88640229614813449", + "data": { + "authorization_type": "OAUTH", + "connection_id": "conn_101644109747323155", + "id": "ca_101649788113519113", + "identifier": "Clark", + "provider": "GOOGLE_ADS", + "status": "ACTIVE", + "token_expires_at": "2025-12-02T06:59:57.237447778Z" + } + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "connected_account.token_refresh_succeeded": { + "post": { + "summary": "Connected Account Token Refresh Succeeded", + "description": "Triggered when token refresh succeeds", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_101651946317808143", + "type": "connected_account.token_refresh_succeeded", + "object": "ConnectedAccount", + "occurred_at": "2025-12-02T06:21:21.517480021Z", + "environment_id": "env_88640229614813449", + "data": { + "authorization_type": "OAUTH", + "connection_id": "conn_101644109747323155", + "id": "ca_101644170698948883", + "identifier": "Pranesh", + "last_used_at": "2025-12-02T06:21:21.393723232Z", + "provider": "GOOGLE_ADS", + "status": "ACTIVE", + "token_expires_at": "2025-12-02T07:21:20.508197312Z" + } + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "connected_account.token_refresh_failed": { + "post": { + "summary": "Connected Account Token Refresh Failed", + "description": "Triggered when token refresh fails", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_101649795042509316", + "type": "connected_account.token_refresh_failed", + "object": "ConnectedAccount", + "occurred_at": "2025-12-02T05:59:59.250126407Z", + "environment_id": "env_88640229614813445", + "data": { + "authorization_type": "OAUTH", + "connection_id": "conn_101644109747323155", + "id": "ca_101649788113519113", + "identifier": "Clark", + "provider": "GOOGLE_ADS", + "status": "ACTIVE", + "token_expires_at": "2025-12-02T06:59:57.237447778Z" + } + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "connected_account.oauth_succeeded": { + "post": { + "summary": "Connected Account OAuth Succeeded", + "description": "Triggered when OAuth authentication succeeds", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_101649484227871236", + "type": "connected_account.oauth_succeeded", + "object": "ConnectedAccount", + "occurred_at": "2025-12-02T05:56:53.994604757Z", + "environment_id": "env_88640229614813449", + "data": { + "authorization_type": "OAUTH", + "connection_id": "conn_101644109747323155", + "id": "ca_101649474950005257", + "identifier": "Bruce", + "provider": "GOOGLE_ADS", + "status": "ACTIVE", + "token_expires_at": "2025-12-02T06:56:52.976081699Z" + } + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + } + }, + "components": { + "securitySchemes": { + "oauth2": { + "type": "oauth2", + "flows": { + "clientCredentials": { + "tokenUrl": "https://$SCALEKIT_ENVIRONMENT_URL/oauth/token", + "scopes": { + "": "No scope required for client credentials flow" + } + } + } + } + }, + "schemas": { + "connected_accountsConnectorType": { + "description": "- OAUTH: OAuth 2.0 authorization with access and refresh tokens\n - API_KEY: Static API key authentication\n - BASIC_AUTH: HTTP Basic Authentication (username/password)\n - BEARER_TOKEN: Bearer token authentication\n - CUSTOM: Custom authentication mechanism\n - BASIC: Basic authentication (alias)", + "type": "string", + "title": "Type of authentication mechanism used for the connected account", + "enum": [ + "OAUTH", + "API_KEY", + "BASIC_AUTH", + "BEARER_TOKEN", + "CUSTOM", + "BASIC" + ] + }, + "connected_accountsConnectorStatus": { + "description": "- ACTIVE: Account is connected and credentials are valid\n - EXPIRED: Access token has expired and needs refresh\n - PENDING_AUTH: Account awaiting user authorization (re-auth initiated)\n - PENDING_VERIFICATION: OAuth complete; awaiting user identity verification\nbefore activation", + "type": "string", + "title": "Status of a connected account indicating its current state", + "enum": [ + "ACTIVE", + "EXPIRED", + "PENDING_AUTH", + "PENDING_VERIFICATION" + ] + }, + "connected_accountsConnectedAccountForList": { + "type": "object", + "title": "Connected account summary for list operations - excludes sensitive authorization details", + "properties": { + "authorization_type": { + "description": "Authorization mechanism type.", + "$ref": "#/components/schemas/connected_accountsConnectorType" + }, + "connection_id": { + "description": "Parent connection configuration reference.", + "type": "string", + "examples": [ + "conn_24834495392086178" + ] + }, + "connector": { + "description": "Connector identifier.", + "type": "string", + "examples": [ + "notion" + ] + }, + "id": { + "description": "Unique connected account identifier.", + "type": "string", + "examples": [ + "ca_24834495392086178" + ] + }, + "identifier": { + "description": "The unique identifier for this account in the third-party service.", + "type": "string", + "examples": [ + "user@example.com" + ] + }, + "last_used_at": { + "description": "Last usage timestamp.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-03-20T14:30:00Z" + ] + }, + "provider": { + "description": "OAuth provider name (e.g., 'google', 'microsoft').", + "type": "string", + "examples": [ + "google" + ] + }, + "status": { + "description": "Current connection status.", + "$ref": "#/components/schemas/connected_accountsConnectorStatus" + }, + "token_expires_at": { + "description": "Token expiration timestamp.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-12-31T23:59:59Z" + ] + }, + "updated_at": { + "description": "Last modification timestamp.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-03-20T15:04:05Z" + ] + } + } + }, + "connected_accountsListConnectedAccountsResponse": { + "type": "object", + "properties": { + "connected_accounts": { + "description": "List of connected accounts matching the filter criteria. Excludes sensitive authorization details for security.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/connected_accountsConnectedAccountForList" + } + }, + "next_page_token": { + "description": "Pagination token for retrieving the next page. Empty if this is the last page. Pass this value to page_token in the next request.", + "type": "string", + "examples": [ + "eyJvZmZzZXQiOjIwfQ==" + ] + }, + "prev_page_token": { + "description": "Pagination token for retrieving the previous page. Empty if this is the first page. Pass this value to page_token to go back.", + "type": "string", + "examples": [ + "eyJvZmZzZXQiOjB9" + ] + }, + "total_size": { + "description": "Total count of connected accounts matching the filter criteria across all pages. Use for calculating pagination.", + "type": "integer", + "format": "int64", + "examples": [ + 100 + ] + } + } + }, + "connected_accountsOauthToken": { + "type": "object", + "title": "OAuth 2.0 access and refresh tokens with scopes", + "properties": { + "access_token": { + "description": "OAuth access token for API requests. Typically short-lived and must be refreshed after expiration.", + "type": "string", + "examples": [ + "ya29.a0AfH6SMBx..." + ] + }, + "domain": { + "description": "Associated domain for workspace or organization-scoped OAuth connections (e.g., Google Workspace domain).", + "type": "string", + "examples": [ + "example.com" + ] + }, + "refresh_token": { + "description": "OAuth refresh token for obtaining new access tokens. Long-lived and used to maintain persistent authorization.", + "type": "string", + "examples": [ + "1//0gHJxZ-Lb2..." + ] + }, + "scopes": { + "description": "List of granted OAuth scopes defining the permissions and access levels for this connection.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "https://www.googleapis.com/auth/drive.readonly", + "https://www.googleapis.com/auth/userinfo.email" + ] + ] + } + } + }, + "connected_accountsStaticAuth": { + "type": "object", + "title": "Static authentication credentials for API keys, bearer tokens, or basic auth", + "properties": { + "details": { + "description": "Flexible JSON structure containing static credentials. Format varies by connector type (API key, username/password, etc.).", + "type": "object", + "examples": [ + { + "api_key": "sk_live_...", + "api_secret": "..." + } + ] + } + } + }, + "connected_accountsAuthorizationDetails": { + "type": "object", + "title": "Authentication credentials container supporting multiple auth types", + "properties": { + "oauth_token": { + "title": "OAuth 2.0 credentials", + "$ref": "#/components/schemas/connected_accountsOauthToken" + }, + "static_auth": { + "title": "Static authentication credentials", + "$ref": "#/components/schemas/connected_accountsStaticAuth" + } + } + }, + "v1connected_accountsUpdateConnectedAccount": { + "type": "object", + "title": "Payload for updating an existing connected account - all fields optional", + "properties": { + "api_config": { + "description": "Updated JSON configuration for API-specific settings. Merges with existing configuration - only provided fields are modified.", + "type": "object", + "examples": [ + { + "rate_limit": 2000, + "timeout": 60 + } + ] + }, + "authorization_details": { + "description": "Updated authentication credentials. Provide new OAuth tokens (e.g., after refresh) or updated static auth details. Only included fields will be modified.", + "$ref": "#/components/schemas/connected_accountsAuthorizationDetails", + "examples": [ + { + "oauth_token": { + "access_token": "ya29.new_token...", + "refresh_token": "1//0g...", + "scopes": [ + "email", + "profile", + "calendar" + ] + } + } + ] + } + } + }, + "connected_accountsUpdateConnectedAccountRequest": { + "type": "object", + "properties": { + "connected_account": { + "description": "Details of the connected account to update", + "$ref": "#/components/schemas/v1connected_accountsUpdateConnectedAccount", + "examples": [ + { + "authorization_details": { + "oauth_token": { + "access_token": "...", + "refresh_token": "...", + "scopes": [ + "read", + "write" + ] + } + }, + "authorization_type": "OAUTH2" + } + ] + }, + "connector": { + "description": "Connector identifier", + "type": "string", + "examples": [ + "notion" + ] + }, + "id": { + "description": "Unique identifier for the connected account to update", + "type": "string", + "examples": [ + "ca_123" + ] + }, + "identifier": { + "description": "The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).", + "type": "string", + "examples": [ + "user@example.com" + ] + }, + "organization_id": { + "description": "Organization ID for the connector", + "type": "string", + "examples": [ + "org_121312434123312" + ] + }, + "user_id": { + "description": "User ID for the connector", + "type": "string", + "examples": [ + "user_121312434123312" + ] + } + } + }, + "connected_accountsConnectedAccount": { + "type": "object", + "properties": { + "api_config": { + "description": "Optional JSON configuration for connector-specific API settings such as rate limits, custom endpoints, or feature flags.", + "type": "object", + "examples": [ + { + "base_url": "https://api.custom-domain.com", + "rate_limit": 1000, + "timeout": 30 + } + ] + }, + "authorization_details": { + "description": "Sensitive authentication credentials including access tokens, refresh tokens, and scopes. Contains either OAuth tokens or static auth details.", + "$ref": "#/components/schemas/connected_accountsAuthorizationDetails" + }, + "authorization_type": { + "description": "Type of authorization mechanism used. Specifies whether this connection uses OAuth, API keys, bearer tokens, or other auth methods.", + "$ref": "#/components/schemas/connected_accountsConnectorType" + }, + "connection_id": { + "description": "Reference to the parent connection configuration. Links this account to a specific connector setup in your environment.", + "type": "string", + "examples": [ + "conn_24834495392086178" + ] + }, + "connector": { + "description": "Connector identifier (e.g., 'notion', 'slack', 'salesforce'). Indicates which third-party application this account connects to.", + "type": "string", + "examples": [ + "notion" + ] + }, + "id": { + "description": "Unique Scalekit-generated identifier for this connected account. Always prefixed with 'ca_'.", + "type": "string", + "examples": [ + "ca_24834495392086178" + ] + }, + "identifier": { + "description": "The unique identifier for this account in the third-party service. Typically an email address, user ID, or workspace identifier.", + "type": "string", + "examples": [ + "user@example.com" + ] + }, + "last_used_at": { + "description": "Timestamp when this connected account was last used to make an API call. Useful for tracking active connections.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-03-20T14:30:00Z" + ] + }, + "provider": { + "description": "OAuth provider name (e.g., 'google', 'microsoft', 'github'). Identifies which authentication service manages this connection.", + "type": "string", + "examples": [ + "google" + ] + }, + "status": { + "description": "Current status of the connected account. Indicates if the account is active, expired, pending authorization, or pending user identity verification.", + "$ref": "#/components/schemas/connected_accountsConnectorStatus" + }, + "token_expires_at": { + "description": "Expiration timestamp for the access token. After this time, the token must be refreshed or re-authorized.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-12-31T23:59:59Z" + ] + }, + "updated_at": { + "description": "Timestamp when this connected account was last modified. Updated whenever credentials or configuration changes.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-03-20T15:04:05Z" + ] + } + } + }, + "connected_accountsUpdateConnectedAccountResponse": { + "type": "object", + "properties": { + "connected_account": { + "description": "The updated connected account with refreshed credentials, new token expiry, and modified configuration settings.", + "$ref": "#/components/schemas/connected_accountsConnectedAccount" + } + } + }, + "v1connected_accountsCreateConnectedAccount": { + "type": "object", + "title": "Payload for creating a new connected account - authorization details are optional", + "properties": { + "api_config": { + "description": "Optional JSON configuration for connector-specific API settings such as rate limits, custom API endpoints, timeouts, or feature flags.", + "type": "object", + "examples": [ + { + "base_url": "https://api.custom-domain.com", + "rate_limit": 1000, + "timeout": 30 + } + ] + }, + "authorization_details": { + "description": "Optional authentication credentials for the connected account. Include OAuth tokens (access_token, refresh_token, scopes) or static auth details (API keys, bearer tokens). Can be provided later via update.", + "$ref": "#/components/schemas/connected_accountsAuthorizationDetails", + "examples": [ + { + "oauth_token": { + "access_token": "ya29.a0...", + "refresh_token": "1//0g...", + "scopes": [ + "email", + "profile" + ] + } + } + ] + } + } + }, + "connected_accountsCreateConnectedAccountRequest": { + "type": "object", + "properties": { + "connected_account": { + "description": "Details of the connected account to create", + "$ref": "#/components/schemas/v1connected_accountsCreateConnectedAccount", + "examples": [ + { + "authorization_details": { + "oauth_token": { + "access_token": "...", + "refresh_token": "...", + "scopes": [ + "read", + "write" + ] + } + }, + "authorization_type": "OAUTH2" + } + ] + }, + "connector": { + "description": "Connector identifier", + "type": "string", + "examples": [ + "notion" + ] + }, + "identifier": { + "description": "The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).", + "type": "string", + "examples": [ + "user@example.com" + ] + }, + "organization_id": { + "description": "Organization ID for the connector", + "type": "string", + "examples": [ + "org_121312434123312" + ] + }, + "user_id": { + "description": "User ID for the connector", + "type": "string", + "examples": [ + "user_121312434123312" + ] + } + } + }, + "connected_accountsCreateConnectedAccountResponse": { + "type": "object", + "properties": { + "connected_account": { + "description": "The newly created connected account with its unique identifier, status, and complete authorization details including access tokens.", + "$ref": "#/components/schemas/connected_accountsConnectedAccount" + } + } + }, + "connected_accountsGetConnectedAccountByIdentifierResponse": { + "type": "object", + "properties": { + "connected_account": { + "description": "The connected account with complete details including sensitive authorization credentials (access tokens, refresh tokens, scopes). Handle with appropriate access controls.", + "$ref": "#/components/schemas/connected_accountsConnectedAccount" + } + } + }, + "connected_accountsGetMagicLinkForConnectedAccountRequest": { + "type": "object", + "properties": { + "connector": { + "description": "Connector identifier", + "type": "string", + "examples": [ + "notion" + ] + }, + "id": { + "description": "Unique identifier for the connected account", + "type": "string", + "examples": [ + "ca_123" + ] + }, + "identifier": { + "description": "The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).", + "type": "string", + "examples": [ + "user@example.com" + ] + }, + "organization_id": { + "description": "Organization ID for the connector", + "type": "string", + "examples": [ + "org_121312434123312" + ] + }, + "state": { + "description": "Optional opaque state value. State added to the user verify redirect URL query params to validate the user verification", + "type": "string", + "examples": [ + "QVNDSUFyY2hhYml0dGVyXzE2ODQ5NzIwNzI0NTY=" + ] + }, + "user_id": { + "description": "User ID for the connector", + "type": "string", + "examples": [ + "user_121312434123312" + ] + }, + "user_verify_url": { + "description": "B2B app's user verify redirect URL", + "type": "string", + "examples": [ + "https://app.yourapp.com/user/verify/callback" + ] + } + } + }, + "connected_accountsGetMagicLinkForConnectedAccountResponse": { + "type": "object", + "properties": { + "expiry": { + "description": "Expiry timestamp for the authentication link", + "type": "string", + "format": "date-time", + "examples": [ + "2024-03-20T15:04:05Z" + ] + }, + "link": { + "description": "Authentication link for the connector", + "type": "string", + "examples": [ + "https://notion.com/oauth/authorize?client_id=..." + ] + } + } + }, + "connected_accountsVerifyConnectedAccountUserRequest": { + "type": "object", + "required": [ + "auth_request_id", + "identifier" + ], + "properties": { + "auth_request_id": { + "description": "Auth request ID as base64url-encoded opaque token from the user verify redirect URL query params", + "type": "string", + "examples": [ + "QVNDSUFyY2hhYml0dGVyXzE2ODQ5NzIwNzI0NTY=" + ] + }, + "identifier": { + "description": "Current logged in user's connected account identifier", + "type": "string", + "examples": [ + "user@example.com" + ] + } + } + }, + "connected_accountsVerifyConnectedAccountUserResponse": { + "type": "object", + "properties": { + "post_user_verify_redirect_url": { + "description": "URL to redirect the user to after successful verification", + "type": "string", + "examples": [ + "https://env1.example.com/connect/success" + ] + } + } + }, + "connected_accountsDeleteConnectedAccountRequest": { + "type": "object", + "properties": { + "connector": { + "description": "Connector identifier", + "type": "string", + "examples": [ + "notion" + ] + }, + "id": { + "description": "Unique identifier for the connected account to delete", + "type": "string", + "examples": [ + "ca_123" + ] + }, + "identifier": { + "description": "The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier).", + "type": "string", + "examples": [ + "user@example.com" + ] + }, + "organization_id": { + "description": "Organization ID for the connector", + "type": "string", + "examples": [ + "org_121312434123312" + ] + }, + "user_id": { + "description": "User ID for the connector", + "type": "string", + "examples": [ + "user_121312434123312" + ] + } + } + }, + "connected_accountsSearchConnectedAccountsResponse": { + "type": "object", + "properties": { + "connected_accounts": { + "description": "List of connected accounts matching the search query. Excludes sensitive authorization details.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/connected_accountsConnectedAccountForList" + } + }, + "next_page_token": { + "description": "Pagination token for the next page. Empty if this is the last page.", + "type": "string", + "examples": [ + "eyJvZmZzZXQiOjMwfQ==" + ] + }, + "prev_page_token": { + "description": "Pagination token for the previous page. Empty if this is the first page.", + "type": "string", + "examples": [ + "eyJvZmZzZXQiOjB9" + ] + }, + "total_size": { + "description": "Total count of accounts matching the search query across all pages.", + "type": "integer", + "format": "int64", + "examples": [ + 100 + ] + } + } + }, + "toolsExecuteToolRequest": { + "type": "object", + "properties": { + "connected_account_id": { + "description": "Optional. The unique ID of the connected account. Use this to directly identify the connected account instead of using identifier + connector combination.", + "type": "string", + "examples": [ + "ca_123" + ] + }, + "connector": { + "description": "Optional. The name of the connector/provider (e.g., 'Google Workspace', 'Slack', 'Notion'). Use this in combination with identifier to identify the connected account.", + "type": "string", + "examples": [ + "Google Workspace" + ] + }, + "identifier": { + "description": "Optional. The unique identifier for the connected account within the third-party service (e.g., email address, user ID, workspace identifier). Use this in combination with connector to identify the connected account.", + "type": "string", + "examples": [ + "user@example.com" + ] + }, + "organization_id": { + "description": "Optional. The organization ID to scope the connected account lookup. Use this to narrow down the search when the same identifier exists across multiple organizations.", + "type": "string", + "examples": [ + "org_123" + ] + }, + "params": { + "description": "JSON object containing the parameters required for tool execution. The structure depends on the specific tool being executed.", + "type": "object", + "examples": [ + { + "body": "Hello World", + "subject": "Hello", + "to": "user@example.com" + } + ] + }, + "tool_name": { + "description": "Name of the tool to execute", + "type": "string", + "examples": [ + "send_email" + ] + }, + "user_id": { + "description": "Optional. The user ID to scope the connected account lookup. Use this to narrow down the search when the same identifier exists across multiple users.", + "type": "string", + "examples": [ + "user_123" + ] + } + } + }, + "toolsExecuteToolResponse": { + "type": "object", + "properties": { + "data": { + "description": "Free-flowing JSON parameters for the tool execution", + "type": "object", + "examples": [ + { + "body": "Hello World", + "subject": "Hello", + "to": "user@example.com" + } + ] + }, + "execution_id": { + "description": "Unique identifier for the tool execution", + "type": "string", + "examples": [ + "123456789" + ] + } + } + }, + "ScalekitEvent": { + "type": "object", + "required": [ + "spec_version", + "id", + "type", + "occurred_at", + "environment_id", + "object" + ], + "properties": { + "spec_version": { + "type": "string", + "example": "1", + "description": "The webhook specification version", + "pattern": "^[0-9]+$" + }, + "id": { + "type": "string", + "pattern": "^evt_", + "example": "evt_1234567890abcdef", + "description": "Unique identifier for the webhook event (must be prefixed with \"evt_\")", + "minLength": 1, + "maxLength": 32 + }, + "type": { + "type": "string", + "example": "organization.created", + "description": "The event type", + "enum": [ + "organization.created", + "organization.updated", + "organization.deleted", + "organization.sso_created", + "organization.sso_deleted", + "organization.sso_enabled", + "organization.sso_disabled", + "user.signup", + "user.login", + "user.logout", + "user.organization_invitation", + "user.organization_membership_created", + "user.organization_membership_updated", + "user.organization_membership_deleted", + "organization.directory.user_created", + "organization.directory.user_updated", + "organization.directory.user_deleted", + "organization.directory.group_created", + "organization.directory.group_updated", + "organization.directory.group_deleted", + "organization.directory_enabled", + "organization.directory_disabled", + "role.created", + "role.updated", + "role.deleted", + "permission.created", + "permission.updated", + "permission.deleted" + ] + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "When the event occurred (ISO 8601 format)", + "example": "2024-01-01T00:00:00Z" + }, + "environment_id": { + "type": "string", + "pattern": "^env_", + "example": "env_1234567890abcdef", + "description": "The environment ID where the event occurred", + "minLength": 1, + "maxLength": 32 + }, + "organization_id": { + "type": "string", + "pattern": "^org_", + "example": "org_1234567890abcdef", + "description": "The organization ID (if applicable)", + "minLength": 1, + "maxLength": 32 + }, + "object": { + "type": "string", + "description": "The type of object that triggered the webhook", + "enum": [ + "Organization", + "Connection", + "Role", + "Directory", + "DirectoryUser", + "DirectoryGroup", + "Permission", + "OrgMembership", + "User" + ], + "example": "Organization" + }, + "data": { + "type": "object", + "description": "The event payload (structure varies by event type)", + "additionalProperties": true, + "example": { + "id": "org_1234567890abcdef", + "name": "Example Organization", + "created_at": "2024-01-01T00:00:00Z" + } + }, + "display_name": { + "type": "string", + "description": "Human-readable display name for the event", + "example": "Organization Created", + "minLength": 1, + "maxLength": 200 + } + } + } + } + } +} \ No newline at end of file diff --git a/public/api/saaskit.scalar.json b/public/api/saaskit.scalar.json new file mode 100644 index 000000000..e9ed39682 --- /dev/null +++ b/public/api/saaskit.scalar.json @@ -0,0 +1,12042 @@ +{ + "openapi": "3.1.1", + "info": { + "description": "# Overview\n\nThe Scalekit API is a RESTful API that enables you to manage organizations, users, and authentication settings. All requests must use HTTPS.\nAll API requests use the following base URLs:\n\n```\nhttps://{your-subdomain}.scalekit.dev (Development)\nhttps://{your-subdomain}.scalekit.com (Production)\nhttps://auth.yourapp.com (Custom domain)\n```\n\nScalekit operates two separate environments: Development and Production. Resources cannot be moved between environments.\n\n## Quickstart\n\nThe Scalekit API uses OAuth 2.0 Client Credentials for authentication.\n\nCopy your API credentials from the Scalekit dashboard's API Config section and set them as environment variables.\n\n```sh\nSCALEKIT_ENVIRONMENT_URL=''\nSCALEKIT_CLIENT_ID=''\nSCALEKIT_CLIENT_SECRET=''\n```\n\nGetting an access token\n\n1. Get your credentials from the [Scalekit Dashboard](https://app.scalekit.com)\n2. Request an access token:\n\n```sh\ncurl https:///oauth/token \\\n -X POST \\\n -H 'Content-Type: application/x-www-form-urlencoded' \\\n -d 'client_id={client_id}' \\\n -d 'client_secret={client_secret}' \\\n -d 'grant_type=client_credentials'\n```\n\n3. Use the access token in API requests:\n\n```sh\ncurl https:///api/v1/organizations \\\n -H 'Content-Type: application/json' \\\n -H 'Authorization: Bearer {access_token}'\n```\n\nThe response includes an access token:\n\n```json\n{\n\t\"access_token\": \"eyJhbGciOiJSUzI1NiIsImtpZCI6InNua181Ok4OTEyMjU2NiIsInR5cCI6IkpXVCJ9...\",\n\t\"token_type\": \"Bearer\",\n\t\"expires_in\": 86399,\n\t\"scope\": \"openid\"\n}\n```\n\n## SDKs\n\nScalekit provides official SDKs for multiple programming languages. Check the changelog at GitHub repositories for the latest updates.\n\n### Node.js\n\n```sh\nnpm install @scalekit-sdk/node\n```\n\nCreate a new Scalekit client instance after initializing the environment variables\n\n```js\nimport { Scalekit } from \"@scalekit-sdk/node\";\n\nexport let scalekit = new Scalekit(\n\tprocess.env.SCALEKIT_ENVIRONMENT_URL,\n\tprocess.env.SCALEKIT_CLIENT_ID,\n\tprocess.env.SCALEKIT_CLIENT_SECRET\n);\n```\n\n[See the Node SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-node/releases)\n\n### Python\n\n```sh\npip install scalekit-sdk-python\n```\n\nCreate a new Scalekit client instance after initializing the environment variables.\n\n```py\nfrom scalekit import ScalekitClient\nimport os\n\nscalekit_client = ScalekitClient(\n os.environ.get('SCALEKIT_ENVIRONMENT_URL'),\n os.environ.get('SCALEKIT_CLIENT_ID'),\n os.environ.get('SCALEKIT_CLIENT_SECRET')\n)\n```\n\n[See the Python SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-python/releases)\n\n### Go\n\n```sh\ngo get -u github.com/scalekit-inc/scalekit-sdk-go\n```\n\nCreate a new Scalekit client instance after initializing the environment variables.\n\n```go\npackage main\n\nimport (\n \"os\"\n \"github.com/scalekit-inc/scalekit-sdk-go\"\n)\n\nscalekitClient := scalekit.NewScalekitClient(\n os.Getenv(\"SCALEKIT_ENVIRONMENT_URL\"),\n os.Getenv(\"SCALEKIT_CLIENT_ID\"),\n os.Getenv(\"SCALEKIT_CLIENT_SECRET\"),\n)\n```\n\n[See the Go SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-go/releases)\n\n### Java\n\n```gradle\n/* Gradle users - add the following to your dependencies in build file */\nimplementation \"com.scalekit:scalekit-sdk-java:2.0.11\"\n```\n\n```xml\n\n\n com.scalekit\n scalekit-sdk-java\n 2.0.11\n\n```\n\n[See the Java SDK changelog](https://github.com/scalekit-inc/scalekit-sdk-java/releases)\n\n### Error handling\n\nThe API uses standard HTTP status codes:\n\n| Code | Description |\n| ----------- | -------------------- |\n| 200/201 | Success |\n| 400 | Invalid request |\n| 401 | Authentication error |\n| 404 | Resource not found |\n| 429 | Rate limit exceeded |\n| 500/501/504 | Server error |\n\nError responses include detailed information:\n\n```json\n{\n\t\"code\": 16,\n\t\"message\": \"Token empty\",\n\t\"details\": [\n\t\t{\n\t\t\t\"@type\": \"type.googleapis.com/scalekit.v1.errdetails.ErrorInfo\",\n\t\t\t\"error_code\": \"UNAUTHENTICATED\"\n\t\t}\n\t]\n}\n```\n", + "title": "Scalekit APIs", + "contact": { + "name": "Scalekit Inc", + "url": "https://scalekit.com", + "email": "support@scalekit.com" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + }, + "version": "1.0.0", + "x-scalar-sdk-installation": [ + { + "lang": "shell", + "description": "Set up OAuth 2.0 Client Credentials authentication to access Scalekit APIs. Includes credential configuration, token exchange, and authenticated API request examples.", + "source": "\n# 1. Obtain API Credentials\n# Get your credentials from the Scalekit dashboard\nexport SCALEKIT_ENVIRONMENT_URL=\"https://your-org.scalekit.dev\" # Your Scalekit environment URL\nexport SCALEKIT_CLIENT_ID=\"your_client_id\" # Your client ID\nexport SCALEKIT_CLIENT_SECRET=\"your_client_secret\" # Your client secret\n\n# 2. Exchange client credentials an OAuth 2.0 access token\nTOKEN_RESPONSE=$(curl -s -X POST \"${SCALEKIT_ENVIRONMENT_URL}/oauth/token\" \\\n -H \"Content-Type: application/x-www-form-urlencoded\" \\\n -d \"client_id=${SCALEKIT_CLIENT_ID}\" \\\n -d \"client_secret=${SCALEKIT_CLIENT_SECRET}\" \\\n -d \"grant_type=client_credentials\")\n\n# 3. Make Authenticated API Requests\ncurl -X GET \"${SCALEKIT_ENVIRONMENT_URL}/api/v1/organizations\" \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n -H \"Accept: application/json\"\n" + } + ] + }, + "servers": [ + { + "url": "https://$SCALEKIT_ENVIRONMENT_URL" + } + ], + "security": [ + { + "oauth2": [] + } + ], + "tags": [ + { + "description": "Organization represents a customer or a tenant of your product. This is the top level entity and all resources are mapped to this Organization object. Each organization is uniquely identified by `organization_id`.\n\n\n", + "name": "Organizations" + }, + { + "description": "Permission management for defining and controlling access to system resources. Create, retrieve, update, and delete granular permissions that represent specific actions users can perform. Permissions are the building blocks of role-based access control (RBAC) and can be assigned to roles to grant users the ability to perform specific operations. Use this service to define custom permissions for your application's unique access control requirements.", + "name": "Permissions" + }, + { + "description": "Comprehensive user management operations including user lifecycle, organization memberships, and invitation workflows. This service provides endpoints for creating, retrieving, updating, and deleting user accounts across your Scalekit environment. It supports both individual user operations and bulk operations for user administration, including user search, pagination, and metadata management. The service also handles user invitations and organization membership management.", + "name": "Users" + }, + { + "description": "Manage enterprise connections for your Scalekit environment. This service provides endpoints for retrieving, and updating connections.", + "name": "Connections" + }, + { + "description": "Directory management for viewing and controlling external identity provider connections in your Scalekit environment. This service provides endpoints for retrieving directory information, listing directories and their contents, and enabling or disabling directory synchronization.", + "name": "Directory" + }, + { + "description": "Role-based access control (RBAC) for defining and managing permissions in an environment. Create and update custom roles with explicit permissions, model role hierarchies through inheritance, view dependent roles, manage role-permission assignments, and list roles and permissions. Also provides a utility to count users assigned to a role.", + "name": "Roles" + }, + { + "description": "Comprehensive session management for user authentication and authorization. This service provides endpoints for retrieving session details, managing user sessions across devices, revoking individual sessions, and terminating all active sessions for a user. It supports session auditing, device tracking, and security monitoring with detailed session metadata including device information, IP geolocation, and activity timestamps.", + "name": "Sessions" + }, + { + "description": "Manage organization-level domains. Scalekit supports two domain types:\n\n- ORGANIZATION_DOMAIN: Used for SSO domain discovery. When a user signs in with a matching email domain, Scalekit routes them to the organization’s SSO provider and enforces SSO.\n- ALLOWED_EMAIL_DOMAIN: Used to mark trusted email domains for an organization. When a user signs in or signs up with a matching domain, Scalekit suggests the organization in the organization switcher (authentication-method agnostic).\n", + "name": "Domains" + }, + { + "description": "Endpoints for managing API client applications. API clients enable secure, automated interactions between software systems without human intervention. Each client is uniquely identified by a `client_id` and can be configured with authentication settings, redirect URIs, and security parameters. Use these endpoints to create, manage, and configure API clients for your API clients.", + "name": "API Auth", + "externalDocs": { + "url": "https://docs.scalekit.com/m2m/overview" + } + }, + { + "description": "Endpoints for sending and verifying passwordless authentication emails. These APIs allow users to authenticate without passwords by receiving a verification code or magic link in their email.", + "name": "Magic link & OTP" + }, + { + "description": "Endpoints for passkey-based authentication using WebAuthn/FIDO2 standards.", + "name": "Passkeys" + } + ], + "externalDocs": { + "description": "Scalekit Docs", + "url": "https://docs.scalekit.com/" + }, + "paths": { + "/api/v1/connections": { + "get": { + "description": "Retrieves a list of connections in the environment", + "tags": [ + "Connections" + ], + "summary": "List connections", + "operationId": "ConnectionService_ListConnections", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Filter connections by organization identifier", + "name": "organization_id", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Filter connections by email domain associated with the organization", + "name": "domain", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Filter connections by status. Use 'all' to include all connections regardless of status. Default behavior shows only active (completed and enabled) connections", + "name": "include", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved connections", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connectionsListConnectionsResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "// List connections by organization id\nconst connections = await scalekit.connection.listConnections(organizationId);\n\n// List connections by domain\nconst connections = await scalekit.connection.listConnectionsByDomain(domain);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "# List connections by organization id\nconnections = scalekit_client.connection.list_connections(\n organization_id\n)\n\n# List connections by domain\nresponse = scalekit_client.connection.list_connections_by_domain(domain=\"example.com\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "// List connections by organization id\nconnections, err := scalekitClient.Connection().ListConnections(\n ctx,\n organizationId\n)\n\n// List connections by domain\nconnections, err := scalekitClient.Connection().ListConnectionsByDomain(ctx, \n domain)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "// List connections by organization id\nListConnectionsResponse response = scalekitClient.connections(\n ).listConnections(organizationId);\n\n// List connections by domain\nListConnectionsResponse response = scalekitClient.connections(\n ).listConnectionsByDomain(\"your-domain.com\");" + } + ] + } + }, + "/api/v1/invites/organizations/{organization_id}/users/{id}/resend": { + "patch": { + "description": "Resends an invitation email to a user who has a pending or expired invitation in the specified organization. If the invitation has expired, a new invitation will be automatically created and sent. If the invitation is still valid, a reminder email will be sent instead. Use this endpoint when a user hasn't responded to their initial invitation and you need to send them a reminder or when the original invitation has expired. The invitation email includes a secure magic link that allows the user to complete their account setup and join the organization. Each resend operation increments the resent counter.", + "tags": [ + "Users" + ], + "summary": "Resend user invitation email", + "operationId": "UserService_ResendInvite", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization containing the pending invitation. Must start with 'org_' and be 1-32 characters long.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "System-generated user ID of the user who has a pending invitation. Must start with 'usr_' and be 19-25 characters long.", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully resent the invitation email. Returns the updated invitation object with organization ID, user ID, membership status, timestamps, and resent count. If expired, a new invitation is created; otherwise, the existing one is resent.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersResendInviteResponse" + } + } + } + }, + "400": { + "description": "Invalid request — common causes include user ID or organization ID is invalid, full-stack authentication is disabled, user profile is missing, invite already accepted, or missing expiry time in user management settings.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/errdetailsErrorInfo" + } + } + } + }, + "404": { + "description": "Resource not found — the specified user, organization, membership, or invitation could not be found in the specified environment. Verify that all IDs are correct and that the resources exist before attempting to resend an invitation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/errdetailsErrorInfo" + } + } + } + }, + "500": { + "description": "Internal server error — an unexpected error occurred while processing the invitation resend request. This may be due to database connectivity issues, problems generating the secure magic link, email delivery service failures, or transaction errors during invitation processing. Contact support if the problem persists.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/errdetailsErrorInfo" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserServiceResendInviteBody" + } + } + }, + "required": true + } + } + }, + "/api/v1/memberships/organizations/{organization_id}/users/{id}": { + "post": { + "description": "Adds an existing user to an organization and assigns them specific roles and permissions. Use this endpoint when you want to grant an existing user access to a particular organization. You can specify roles, metadata, and other membership details during the invitation process.", + "tags": [ + "Users" + ], + "summary": "Add existing user to organization", + "operationId": "UserService_CreateMembership", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the target organization. Must start with 'org_' and be 1-32 characters long.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "System-generated user ID. Must start with 'usr_' (19-25 characters)", + "name": "id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "External system identifier from connected directories. Must be unique across the system", + "name": "external_id", + "in": "query" + }, + { + "schema": { + "type": "boolean" + }, + "description": "If true, sends an activation email to the user. Defaults to true.", + "name": "send_invitation_email", + "in": "query" + } + ], + "responses": { + "201": { + "description": "User successfully added to the organization. Returns details of the updated membership details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersCreateMembershipResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "import { ScalekitClient } from \"@scalekit-sdk/node\";\nconst scalekit = new ScalekitClient(\n\tprocess.env.SCALEKIT_ENV_URL,\n\tprocess.env.SCALEKIT_CLIENT_ID,\n\tprocess.env.SCALEKIT_CLIENT_SECRET\n);\nawait scalekit.user.createMembership(\"org_123\", \"usr_123\", {\n\troles: [\"admin\"],\n\tmetadata: {\n\t\tdepartment: \"engineering\",\n\t\tlocation: \"nyc-office\",\n\t},\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "from scalekit.v1.users.users_pb2 import CreateMembership\nfrom scalekit.v1.commons.commons_pb2 import Role\n\nmembership = CreateMembership(\n roles=[Role(name=\"admin\")],\n metadata={\"department\": \"engineering\", \"location\": \"nyc-office\"},\n)\nresp = scalekit_client.users.create_membership(\n organization_id=\"org_123\",\n user_id=\"usr_123\",\n membership=membership,\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "func main() {\n scalekitClient := scalekit.NewScalekitClient(\n os.Getenv(\"SCALEKIT_ENV_URL\"),\n os.Getenv(\"SCALEKIT_CLIENT_ID\"),\n os.Getenv(\"SCALEKIT_CLIENT_SECRET\"),\n )\n membership := &usersv1.CreateMembership{\n Roles: []*usersv1.Role{{Name: \"admin\"}},\n Metadata: map[string]string{\n \"department\": \"engineering\",\n \"location\": \"nyc-office\",\n },\n }\n resp, \n err := scalekitClient.User().CreateMembership(\n context.Background(), \"org_123\", \n \"usr_123\", membership, false)\n if err != nil {\n panic(err)\n }\n}" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "import com.scalekit.ScalekitClient;\nimport com.scalekit.api.UserClient;\nimport com.scalekit.grpc.scalekit.v1.users.*;\nScalekitClient scalekitClient = new ScalekitClient(\n System.getenv(\"SCALEKIT_ENV_URL\"),\n System.getenv(\"SCALEKIT_CLIENT_ID\"),\n System.getenv(\"SCALEKIT_CLIENT_SECRET\")\n);\nUserClient users = scalekitClient.users();\nCreateMembershipRequest membershipReq = CreateMemb\n ershipRequest.newBuilder()\n .setMembership(\n CreateMembership.newBuilder()\n .addRoles(Role.newBuilder(\n ).setName(\"admin\").build())\n .putMetadata(\"department\", \"engineering\")\n .putMetadata(\"location\", \"nyc-office\")\n .build())\n .build();\nCreateMembershipResponse res = users.\n createMembership(\"org_123\", \"usr_123\", \n membershipReq);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Membership details to create. Required fields must be provided.", + "$ref": "#/components/schemas/v1usersCreateMembership" + } + } + }, + "required": true + } + }, + "delete": { + "description": "Removes a user from an organization by user ID or external ID. If the user has no memberships left and cascade is true, the user is also deleted. This action is irreversible and may also remove related group memberships.", + "tags": [ + "Users" + ], + "summary": "Delete organization membership for user", + "operationId": "UserService_DeleteMembership", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique organization identifier. Must start with 'org_' and be 1-32 characters long", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "System-generated user ID. Must start with 'usr_' (19-25 characters)", + "name": "id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "External system identifier from connected directories. Must match existing records", + "name": "external_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "User successfully marked for deletion. No content returned", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Python SDK", + "lang": "python", + "source": "response = scalekit_client.users.delete_membership(\n organization_id=org_id,user_id=user_id\n)" + } + ] + }, + "patch": { + "description": "Updates a user's membership details within an organization by user ID or external ID. You can update roles and membership metadata.", + "tags": [ + "Users" + ], + "summary": "Update organization membership for user", + "operationId": "UserService_UpdateMembership", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization containing the membership. Must start with 'org_' and be 1-32 characters long.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "System-generated user ID. Must start with 'usr_' and be 19-25 characters long.", + "name": "id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Your application's unique identifier for this user.", + "name": "external_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Membership updated successfully. Returns the updated user object.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersUpdateMembershipResponse" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Membership fields to update. Only specified fields will be modified.", + "$ref": "#/components/schemas/v1usersUpdateMembership", + "examples": [ + { + "role": "admin" + } + ] + } + } + }, + "required": true + } + } + }, + "/api/v1/organizations": { + "get": { + "description": "Retrieve a paginated list of organizations within your environment. The response includes a `page_token` that can be used to access subsequent pages of results.", + "tags": [ + "Organizations" + ], + "summary": "List organizations", + "operationId": "OrganizationService_ListOrganization", + "parameters": [ + { + "schema": { + "type": "integer", + "format": "int64" + }, + "description": "Maximum number of organizations to return per page. Must be between 10 and 100", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Pagination token from the previous response. Use to retrieve the next page of organizations", + "name": "page_token", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Your application's unique identifier for this organization, used to link Scalekit with your system", + "name": "external_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of organizations", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/organizationsListOrganizationsResponse" + } + } + } + }, + "400": { + "description": "Invalid page token", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const organizations = await scalekit.organization.listOrganization({\n\tpageSize: 10,\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "options = ListOrganizationOptions()\noptions.page_size = 10\n\norganizations = scalekit_client.organization.list_organizations(\n options=options\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "organizations, err := scalekitClient.Organization.ListOrganizations(\n ctx,\n &scalekit.ListOrganizationOptions{\n PageSize: 10,\n }\n)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListOrganizationsResponse organizations = scalekitClient.organizations().listOrganizations(10, \"\");" + } + ] + }, + "post": { + "description": "Creates a new organization in your environment. Use this endpoint to add a new tenant that can be configured with various settings and metadata", + "tags": [ + "Organizations" + ], + "summary": "Create an organization", + "operationId": "OrganizationService_CreateOrganization", + "responses": { + "201": { + "description": "Returns the newly created organization with its unique identifier and settings", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/organizationsCreateOrganizationResponse" + } + } + } + } + }, + "x-badges": [ + { + "name": "" + } + ], + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const organization = await scalekit.organization.createOrganization(name, {\n\n\texternalId: \"externalId\",\n\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "options = CreateOrganizationOptions()\noptions.external_id = \"externalId\"\norganization = scalekit_client.organization.create_organization(\n name,\n options=options\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "organization, err := ScalekitClient.Organization.CreateOrganization(\n ctx,\n name,\n scalekit.CreateOrganizationOptions{\n ExternalID: \"externalId\",\n },\n)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "CreateOrganization createOrganization = CreateOrganization.newBuilder()\n .setDisplayName(\"Test Org\")\n .build();\n\nOrganization createdOrganization = scalekitClient.organizations().create(createOrganization);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Required parameters for creating a new organization", + "$ref": "#/components/schemas/v1organizationsCreateOrganization" + } + } + }, + "description": "Organization details", + "required": true + } + } + }, + "/api/v1/organizations/{id}": { + "get": { + "description": "Retrieves organization details by Scalekit ID, including name, region, metadata, and settings", + "tags": [ + "Organizations" + ], + "summary": "Get organization details", + "operationId": "OrganizationService_GetOrganization", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique scalekit-generated identifier that uniquely references an organization", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Returns the complete organization object with ID, display name, settings, and metadata", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/organizationsGetOrganizationResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const scalekit = new ScalekitClient(\n ,\n ,\n \n);\n\nconst organization = await scalekit.organization.getOrganization(organization_id);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "scalekit_client = ScalekitClient(\n ,\n ,\n \n)\n\norganization = scalekit_client.organization.get_organization(\n organization_id\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "scalekitClient := scalekit.NewScalekitClient(\n ,\n ,\n \n)\n\norganization, err := scalekitClient.Organization.GetOrganization(\n ctx,\n organizationId\n)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ScalekitClient scalekitClient = new ScalekitClient(\n \"\",\n \"\",\n \"\"\n);\n\nOrganization organization = scalekitClient.organizations().getById(organizationId);" + } + ] + }, + "delete": { + "description": "Remove an existing organization from the environment using its unique identifier", + "tags": [ + "Organizations" + ], + "summary": "Delete an organization", + "operationId": "OrganizationService_DeleteOrganization", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique scalekit-generated identifier that uniquely references an organization", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Organization successfully deleted and no longer accessible", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.organization.deleteOrganization(organizationId);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "scalekit_client.organization.delete_organization(organization_id)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "err := scalekitClient.Organization.DeleteOrganization(\n ctx,\n organizationId\n)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ScalekitClient scalekitClient = new ScalekitClient(\n \"\",\n \"\",\n \"\"\n);\n\nscalekitClient.organizations().deleteById(organizationId);" + } + ] + }, + "patch": { + "description": "Updates an organization's display name, external ID, or metadata. Requires a valid organization identifier. Region code cannot be modified through this endpoint.", + "tags": [ + "Organizations" + ], + "summary": "Update organization details", + "operationId": "OrganizationService_UpdateOrganization", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization to be updated", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Returns the updated organization with all current details reflected in the response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/organizationsUpdateOrganizationResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const organization = await scalekit.organization.updateOrganization(organization_id, {\n displayName: 'displayName',\n externalId: 'externalId',\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "organization = scalekit_client.organization.update_organization(organization_id, {\n display_name: \"display_name\",\n external_id: \"external_id\"\n})" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "organization, err := scalekitClient.Organization.UpdateOrganization(\n ctx,\n organizationId,\n &scalekit.UpdateOrganization{\n DisplayName: \"displayName\",\n ExternalId: \"externalId\",\n },\n)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "UpdateOrganization updateOrganization = UpdateOrganization.newBuilder()\n .setDisplayName(\"Updated Organization Name\")\n .build();\n\nOrganization updatedOrganizationById = scalekitClient.organizations().updateById(organizationId, updateOrganization);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Organization Parameters to be updated", + "$ref": "#/components/schemas/v1organizationsUpdateOrganization" + } + } + }, + "required": true + } + } + }, + "/api/v1/organizations/{id}/portal_links": { + "put": { + "description": "Creates a single use Admin Portal URL valid for 1 minute. Once the generated admin portal URL is accessed or rendered, a temporary session of 6 hours is created to allow the admin to update SSO/SCIM configuration.", + "tags": [ + "Organizations" + ], + "summary": "Generate admin portal link", + "operationId": "OrganizationService_GeneratePortalLink", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Organization ID", + "name": "id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "array", + "items": { + "enum": [ + "dir_sync", + "sso" + ], + "type": "string" + } + }, + "style": "form", + "explode": true, + "description": "Features to enable in the admin portal link. To enable features, append them as URL parameters:\n\n- Single Sign-On: ?features=sso\n- Directory Sync: ?features=dir_sync\n- Both features: ?features=sso&features=dir_sync\n\nExample URL: https://scalekit.com/portal/lnk_123?features=sso\n\n - dir_sync: Enables directory synchronization configuration in the portal\n - sso: Enables Single Sign-On (SSO) configuration in the portal", + "name": "features", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Admin Portal link generated successfully. Returns the portal URL and expiration timestamp.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/organizationsGeneratePortalLinkResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const link = await scalekit.organization.generatePortalLink(organizationId);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "link = scalekit_client.organization.generate_portal_link(\n organization_id\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "link, err := scalekitClient.Organization.GeneratePortalLink(\n ctx,\n organizationId\n)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "Link portalLink = client\n .organizations()\n .generatePortalLink(organizationId, Arrays.asList(Feature.sso, Feature.dir_sync));" + } + ] + } + }, + "/api/v1/organizations/{id}/settings": { + "patch": { + "description": "Updates configuration settings for an organization. Supports modifying SSO configuration, directory synchronization settings, and session parameters. Requires organization ID and the specific settings to update.", + "tags": [ + "Organizations" + ], + "summary": "Toggle organization settings", + "operationId": "OrganizationService_UpdateOrganizationSettings", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization to update settings. Must begin with 'org_' prefix", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Returns the complete organization object with updated settings applied. Contains all organization details including ID, display name, and the modified settings.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/organizationsGetOrganizationResponse" + } + } + } + }, + "400": { + "description": "Invalid request - occurs when the settings payload contains invalid values or unsupported configuration", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Organization not found - the specified organization ID doesn't exist", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const settings = {\n features: [\n {\n name: 'sso',\n enabled: true,\n },\n {\n name: 'dir_sync',\n enabled: true,\n },\n ],\n};\n\nawait scalekit.organization.updateOrganizationSettings('', settings);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "settings = [\n {\n \"name\": \"sso\",\n \"enabled\": True\n },\n {\n \"name\": \"dir_sync\",\n \"enabled\": True\n }\n ]\n\nscalekit_client.organization.update_organization_settings(\n organization_id='', settings=settings\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "settings := OrganizationSettings{\n\n\t\tFeatures: []Feature{\n\n\t\t\t{\n\n\t\t\t\tName: \"sso\",\n\n\t\t\t\tEnabled: true,\n\n\t\t\t},\n\n\t\t\t{\n\n\t\t\t\tName: \"dir_sync\",\n\n\t\t\t\tEnabled: true,\n\n\t\t\t},\n\n\t\t},\n\n\t}\n\n\norganization,err := scalekitClient.Organization().UpdateOrganizationSettings(ctx, organizationId, settings)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "OrganizationSettingsFeature featureSSO = OrganizationSettingsFeature.newBuilder()\n .setName(\"sso\")\n .setEnabled(true)\n .build();\n\nOrganizationSettingsFeature featureDirectorySync = OrganizationSettingsFeature.newBuilder()\n .setName(\"dir_sync\")\n .setEnabled(true)\n .build();\n\nupdatedOrganization = scalekitClient.organizations()\n .updateOrganizationSettings(organization.getId(), List.of(featureSSO,\nfeatureDirectorySync));" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Settings configuration to apply to the organization. Contains feature toggles for SSO, directory synchronization, and other organization capabilities", + "$ref": "#/components/schemas/organizationsOrganizationSettings", + "examples": [ + { + "features": [ + { + "enabled": true, + "name": "sso" + }, + { + "enabled": false, + "name": "directory_sync" + } + ] + } + ] + } + } + }, + "required": true + } + } + }, + "/api/v1/organizations/{org_id}/roles": { + "get": { + "description": "Retrieves all environment roles and organization specific roles. Use this endpoint to view all role definitions, including custom roles and their configurations. You can optionally include permission details for each role to understand their capabilities. This is useful for role management, auditing organization access controls, or understanding the available access levels within the organization.", + "tags": [ + "Roles" + ], + "summary": "List organization roles", + "operationId": "RolesService_ListOrganizationRoles", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "org_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Include additional data in the response. Valid values: 'permissions' (direct permissions only), 'permissions:all' (includes inherited permissions)", + "name": "include", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved list of organization roles. Returns all roles with their metadata and optionally their permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesListOrganizationRolesResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.role.listOrganizationRoles(\"org_123\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.roles.list_organization_roles(org_id=\"org_123\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().ListOrganizationRoles(ctx, \"org_123\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListOrganizationRolesResponse res = scalekitClient.roles().listOrganizationRoles(\"org_123\");" + } + ] + }, + "post": { + "description": "Creates a new role within the specified organization with basic configuration including name, display name, description, and permissions. Use this endpoint to define custom roles that can be assigned to users within the organization. You can create hierarchical roles by extending existing roles and assign specific permissions to control access levels. The role will be scoped to the organization and can be used for organization-specific access control.", + "tags": [ + "Roles" + ], + "summary": "Create organization role", + "operationId": "RolesService_CreateOrganizationRole", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "org_id", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "description": "Organization role created successfully. Returns the complete role object with system-generated ID and timestamps.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesCreateOrganizationRoleResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.role.createOrganizationRole(\"org_123\", {\n name: \"org_admin\",\n displayName: \"Org Admin\",\n description: \"Organization-scoped role\",\n extends: \"base_role_name\", // optional\n permissions: [\"perm.read\", \"perm.write\"] // optional\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "from scalekit.v1.roles.roles_pb2 import CreateOrganizationRole\n\nrole = CreateOrganizationRole(\n name=\"org_admin\",\n display_name=\"Org Admin\",\n description=\"Organization-scoped role\",\n extends=\"base_role_name\", # optional\n permissions=[\"perm.read\", \"perm.write\"] # optional\n)\n\nscalekit_client.roles.create_organization_role(\n org_id=\"org_123\",\n role=role\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().CreateOrganizationRole(ctx, \"org_123\", &rolesv1.CreateOrganizationRole{\n\n\tName: \"org_admin\",\n\n\tDisplayName: \"Org Admin\",\n\n\tDescription: proto.String(\"Organization-scoped role\"), // optional\n\n\tExtends: proto.String(\"base_role_name\"), // optional\n\n\tPermissions: []string{\"perm.read\", \"perm.write\"}, // optional\n\n})" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "CreateOrganizationRoleResponse res = scalekitClient.roles().createOrganizationRole(\n \"org_123\",\n CreateOrganizationRoleRequest.newBuilder()\n .setOrgId(\"org_123\")\n .setRole(\n CreateOrganizationRole.newBuilder()\n .setName(\"org_admin\")\n .setDisplayName(\"Org Admin\")\n .setDescription(\"Organization-scoped role\")\n .setExtends(\"base_role_name\") // optional\n .addPermissions(\"perm.read\") // optional\n .addPermissions(\"perm.write\") // optional\n .build()\n )\n .build()\n);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Organization role details", + "$ref": "#/components/schemas/v1rolesCreateOrganizationRole" + } + } + }, + "required": true + } + } + }, + "/api/v1/organizations/{org_id}/roles/{role_name}": { + "get": { + "description": "Retrieves complete information for a specific organization role including metadata, inheritance details, and optionally permissions. Use this endpoint to audit role configuration and understand the role's place in the organization's role hierarchy. You can include permission details to see what capabilities the role provides. This operation is useful for role management, user assignment decisions, or understanding organization access controls.", + "tags": [ + "Roles" + ], + "summary": "Get organization role details", + "operationId": "RolesService_GetOrganizationRole", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "org_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique name of the role", + "name": "role_name", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Include additional data in the response. Valid values: 'permissions' (direct permissions only), 'permissions:all' (includes inherited permissions)", + "name": "include", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved organization role details. Returns the role object including metadata and inheritance details. Permissions are included only when requested via the include parameter.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesGetOrganizationRoleResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.role.getOrganizationRole(\"org_123\", \"org_admin\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.roles.get_organization_role(\n org_id=\"org_123\",\n role_name=\"org_admin\"\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().GetOrganizationRole(ctx, \"org_123\", \"org_admin\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "GetOrganizationRoleResponse res = scalekitClient.roles().getOrganizationRole(\"org_123\", \"org_admin\");" + } + ] + }, + "put": { + "description": "Modifies an existing organization role's properties including display name, description, permissions, and inheritance settings. Use this endpoint to update role metadata, change permission assignments, or modify role hierarchy within the organization. Only the fields you specify will be updated, leaving other properties unchanged. When updating permissions, the new list replaces all existing permissions for the role.", + "tags": [ + "Roles" + ], + "summary": "Update organization role", + "operationId": "RolesService_UpdateOrganizationRole", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "org_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique name of the role", + "name": "role_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Organization role updated successfully. Returns the modified role object with updated timestamps.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesUpdateOrganizationRoleResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.role.updateOrganizationRole(\"org_123\", \"org_admin\", {\n displayName: \"Org Admin (Updated)\",\n description: \"Updated org role description\"\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "from scalekit.v1.roles.roles_pb2 import UpdateRole\n\nscalekit_client.roles.update_organization_role(\n org_id=\"org_123\",\n role_name=\"org_admin\",\n role=UpdateRole(\n display_name=\"Org Admin (Updated)\",\n description=\"Updated org role description\"\n )\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().UpdateOrganizationRole(ctx, \"org_123\", \"org_admin\", &rolesv1.UpdateRole{\n DisplayName: \"Org Admin (Updated)\",\n Description: \"Updated org role description\",\n})\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "UpdateOrganizationRoleResponse res = scalekitClient.roles().updateOrganizationRole(\n \"org_123\",\n \"org_admin\",\n UpdateOrganizationRoleRequest.newBuilder()\n .setRole(\n UpdateRole.newBuilder()\n .setDisplayName(\"Org Admin (Updated)\")\n .setDescription(\"Updated org role description\")\n .build()\n )\n .build()\n);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Organization role details", + "$ref": "#/components/schemas/v1rolesUpdateRole" + } + } + }, + "required": true + } + }, + "delete": { + "description": "Permanently removes a role from the organization and optionally reassigns users who had that role to a different role. Use this endpoint when you need to clean up unused roles or restructure your organization's access control system. If users are assigned to the role being deleted, you can provide a reassign_role_name to move those users to a different role before deletion. This action cannot be undone, so ensure no critical users depend on the role before deletion.", + "tags": [ + "Roles" + ], + "summary": "Delete organization role", + "operationId": "RolesService_DeleteOrganizationRole", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "org_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique name of the role", + "name": "role_name", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Role name to reassign users to when deleting this role", + "name": "reassign_role_name", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Organization role successfully deleted and users reassigned if specified. No content returned.", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "// Basic delete\nawait scalekit.role.deleteOrganizationRole(\"org_123\", \"org_role_admin\");\n\n// With reassignment\nawait scalekit.role.deleteOrganizationRole(\"org_123\", \"org_role_admin\", \"org_role_member\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "# Basic delete\nscalekit_client.roles.delete_organization_role(\n org_id=\"org_123\",\n role_name=\"org_role_admin\"\n)\n\n# With reassignment\nscalekit_client.roles.delete_organization_role(\n org_id=\"org_123\",\n role_name=\"org_role_admin\",\n reassign_role_name=\"org_role_member\"\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "// Basic delete\nerr := scalekitClient.Role().DeleteOrganizationRole(ctx, \"org_123\", \"org_role_admin\")\nif err != nil { /* handle err */ }\n\n// With reassignment\nerr = scalekitClient.Role().DeleteOrganizationRole(ctx, \"org_123\", \"org_role_admin\", \"org_role_member\")" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "// Basic delete\nscalekitClient.roles().deleteOrganizationRole(\"org_123\", \"org_role_admin\");\n\n// With reassignment\nscalekitClient.roles().deleteOrganizationRole(\"org_123\", \"org_role_admin\", \"org_role_member\");" + } + ] + } + }, + "/api/v1/organizations/{org_id}/roles:set_defaults": { + "patch": { + "description": "Updates the default member role for the specified organization. Use this endpoint to configure which role is automatically assigned to new users when they join the organization. The system will validate that the specified role exists and update the organization settings accordingly. This configuration affects all new user invitations and memberships within the organization.", + "tags": [ + "Roles" + ], + "summary": "Set default organization roles", + "operationId": "RolesService_UpdateDefaultOrganizationRoles", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "org_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Default organization roles updated successfully. Returns the updated default member role object with complete role information.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesUpdateDefaultOrganizationRolesResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.role.updateDefaultOrganizationRoles(\"org_123\", {\n defaultMemberRole: \"org_member\"\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "from scalekit.v1.roles.roles_pb2 import UpdateDefaultOrganizationRolesRequest\n\nres = scalekit_client.roles.update_default_organization_roles(\n org_id=\"org_123\",\n default_roles=UpdateDefaultOrganizationRolesRequest(\n default_member_role=\"org_member\"\n )\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().UpdateDefaultOrganizationRoles(ctx, \"org_123\", \"org_member\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "UpdateDefaultOrganizationRolesResponse res = scalekitClient.roles().updateDefaultOrganizationRoles(\n \"org_123\",\n UpdateDefaultOrganizationRolesRequest.newBuilder()\n .setDefaultMemberRole(\"org_member\")\n .build()\n);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RolesServiceUpdateDefaultOrganizationRolesBody" + } + } + }, + "required": true + } + } + }, + "/api/v1/organizations/{organization_id}/clients": { + "get": { + "description": "Retrieves a paginated list of API clients for a specific organization. Returns client details including metadata, scopes, and secret information (without exposing actual secret values).", + "tags": [ + "API Auth" + ], + "summary": "List organization API clients", + "operationId": "ClientService_ListOrganizationClients", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization whose clients to list. Must start with 'org_' prefix.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "integer", + "format": "int64" + }, + "description": "Maximum number of clients to return per page\n\nMaximum number of API clients to return per page. Must be between 10 and 100", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Pagination token from the previous response\n\nPagination token from the previous response. Use to retrieve the next page of organization clients", + "name": "page_token", + "in": "query" + } + ], + "responses": { + "200": { + "description": "List of organization API clients returned successfully. Each client includes its configuration details and metadata.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/clientsListOrganizationClientsResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Python SDK", + "lang": "python", + "source": "# List clients for a specific organization\norg_id = 'SCALEKIT_ORGANIZATION_ID'\n\n# Retrieve all clients with default pagination\nresponse = scalekit_client.m2m_client.list_organization_clients(\n organization_id=org_id,\n page_size=30\n)\n\n# Access the clients list\nclients = response.clients\nfor client in clients:\n print(f\"Client ID: {scalekit_client.id}, Name: {scalekit_client.name}\")" + } + ] + }, + "post": { + "description": "Creates a new API client for an organization. Returns the client details and a plain secret (available only once).", + "tags": [ + "API Auth" + ], + "summary": "Create organization API client", + "operationId": "ClientService_CreateOrganizationClient", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "organization_id", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "description": "API client created successfully. Returns the client ID and plain secret (only available at creation time). The client can be configured with scopes, audience values, and custom claims for fine-grained access control.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/clientsCreateOrganizationClientResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Python SDK", + "lang": "python", + "source": "from scalekit.v1.clients.clients_pb2 import OrganizationClient\n\nm2m_client = OrganizationClient(\n name=\"GitHub Actions Deployment Service\",\n description=\"Service account for GitHub Actions to deploy applications\nto production\",\n custom_claims=[\n {\"key\": \"github_repository\", \"value\": \"acmecorp/inventory-service\"},\n {\"key\": \"environment\", \"value\": \"production_us\"}\n ],\n scopes=[\"deploy:applications\", \"read:deployments\"],\n audience=[\"deployment-api.acmecorp.com\"],\n expiry=3600\n)\n\nresponse = scalekit_client.m2m_client.create_organization_client(\n organization_id=\"SCALEKIT_ORGANIZATION_ID\",\n m2m_client=m2m_client\n)" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Details of the client to be created", + "$ref": "#/components/schemas/clientsOrganizationClient" + } + } + }, + "required": true + } + } + }, + "/api/v1/organizations/{organization_id}/clients/{client_id}": { + "get": { + "description": "Retrieves details of a specific API client in an organization.", + "tags": [ + "API Auth" + ], + "summary": "Get organization API client", + "operationId": "ClientService_GetOrganizationClient", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the API client", + "name": "client_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Returns the complete API client configuration, including all current settings and a list of active secrets. Note that secret values are not included in the response for security reasons.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/clientsGetOrganizationClientResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Python SDK", + "lang": "python", + "source": "# Get client ID from environment variables\norg_id = 'SCALEKIT_ORGANIZATION_ID'\nclient_id = os.environ['M2M_CLIENT_ID']\n\n# Fetch client details for the specified organization\nresponse = scalekit_client.m2m_client.get_organization_client(\n organization_id=org_id,\n client_id=client_id\n)" + } + ] + }, + "delete": { + "description": "Permanently deletes an API client from an organization. This operation cannot be undone and will revoke all access for the client. All associated secrets will also be invalidated. Use this endpoint to remove unused or compromised clients.", + "tags": [ + "API Auth" + ], + "summary": "Delete organization API client", + "operationId": "ClientService_DeleteOrganizationClient", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization that owns the client. Must start with 'org_' prefix.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the API client to permanently delete. Must start with 'm2morg_' prefix.", + "name": "client_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Organization API client successfully deleted and no longer accessible", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Python SDK", + "lang": "python", + "source": "# Get client ID from environment variables\norg_id = ''\nclient_id = os.environ['M2M_CLIENT_ID']\n\n# Delete the specified client from the organization\nresponse = scalekit_client.m2m_client.delete_organization_client(\n organization_id=org_id,\n client_id=client_id\n)" + } + ] + }, + "patch": { + "description": "Updates an existing organization API client. Only specified fields are modified.", + "tags": [ + "API Auth" + ], + "summary": "Update organization API client", + "operationId": "ClientService_UpdateOrganizationClient", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the client", + "name": "client_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Returns the updated organization API client with all current details reflected in the response, including modified scopes, audience values, and custom claims.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/clientsUpdateOrganizationClientResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Python SDK", + "lang": "python", + "source": "from scalekit.v1.clients.clients_pb2 import OrganizationClient\n\norg_id = ''\nclient_id = os.environ['M2M_CLIENT_ID']\n\nupdate_m2m_client = OrganizationClient(\n description=\"Service account for GitHub Actions to deploy applications\nto production_eu\",\n custom_claims=[\n {\"key\": \"github_repository\", \"value\": \"acmecorp/inventory\"},\n {\"key\": \"environment\", \"value\": \"production_eu\"}\n ]\n)\n\nresponse = scalekit_client.m2m_client.update_organization_client(\n organization_id=org_id,\n client_id=client_id,\n m2m_client=update_m2m_client\n)" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Updated details for the client", + "$ref": "#/components/schemas/clientsOrganizationClient" + } + } + }, + "required": true + } + } + }, + "/api/v1/organizations/{organization_id}/clients/{client_id}/secrets": { + "post": { + "description": "Creates a new secret for an organization API client. Returns the plain secret (available only once).", + "tags": [ + "API Auth" + ], + "summary": "Create organization API client secret", + "operationId": "ClientService_CreateOrganizationClientSecret", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the API client", + "name": "client_id", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "description": "Client secret created successfully. Returns the new secret ID and the plain secret value (only available at creation time). The secret can be used immediately for authentication.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/clientsCreateOrganizationClientSecretResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Python SDK", + "lang": "python", + "source": "# Get client ID from environment variables\norg_id = 'SCALEKIT_ORGANIZATION_ID'\nclient_id = os.environ['M2M_CLIENT_ID']\n\n# Add a new secret to the specified client\nresponse = scalekit_client.m2m_client.add_organization_client_secret(\n organization_id=org_id,\n client_id=client_id\n)\n\n# Extract the secret ID from the response\nsecret_id = response[0].secret.id" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/clients/{client_id}/secrets/{secret_id}": { + "delete": { + "description": "Permanently deletes a secret from an organization API client. This operation cannot be undone.", + "tags": [ + "API Auth" + ], + "summary": "Delete organization API client secret", + "operationId": "ClientService_DeleteOrganizationClientSecret", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the API client", + "name": "client_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the client secret", + "name": "secret_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Client secret successfully deleted and no longer accessible", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Python SDK", + "lang": "python", + "source": "# Get client and secret IDs from environment variables\norg_id = ''\nclient_id = os.environ['M2M_CLIENT_ID']\nsecret_id = os.environ['M2M_SECRET_ID']\n\n# Remove the specified secret from the client\nresponse = scalekit_client.m2m_client.remove_organization_client_secret(\n organization_id=org_id,\n client_id=client_id,\n secret_id=secret_id\n)" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/connections/{id}": { + "get": { + "description": "Retrieves the complete configuration and status details for a specific connection by its ID within an organization. Returns all connection properties including provider settings, protocols, and current status.", + "tags": [ + "Connections" + ], + "summary": "Get connection details", + "operationId": "ConnectionService_GetConnection", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Organization identifier (required). Specifies which organization owns the connection you want to retrieve.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Connection identifier (required). Specifies which specific connection to retrieve from the organization.", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved connection details for the specified organization", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connectionsGetConnectionResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const connection = await scalekit.connection.getConnection(\n organizationId,\n connectionId\n);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "connection = scalekit_client.connection.get_connection(\n organization_id,\n connection_id,\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "connection, err := scalekitClient.Connection.GetConnection(\n ctx,\n organizationId,\n connectionId,\n)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "Connection connection = scalekitClient.connections().getConnectionById(connectionId, organizationId);" + } + ] + }, + "delete": { + "description": "Deletes an SSO connection from the specified organization by connection ID. Use this endpoint when an identity provider integration is no longer needed for the organization. Returns an empty response after the SSO connection is deleted successfully.", + "tags": [ + "Connections" + ], + "summary": "Delete SSO connection", + "operationId": "ConnectionService_DeleteConnection", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Organization ID for the Connection.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Connection ID. Unique ID for the connection", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "SSO connection deleted successfully", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.connection.deleteConnection(organizationId, connectionId);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "scalekit_client.connection.delete_connection(\n organization_id,\n connection_id\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "err := scalekitClient.Connection.DeleteConnection(\n ctx,\n organizationId,\n connectionId,\n)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "scalekitClient.connections().deleteConnection(connectionId, organizationId);" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/connections/{id}:disable": { + "patch": { + "description": "Deactivate an existing connection for the specified organization. When disabled, users cannot authenticate using this connection. This endpoint changes the connection state from enabled to disabled without modifying other configuration settings", + "tags": [ + "Connections" + ], + "summary": "Disable SSO connection", + "operationId": "ConnectionService_DisableConnection", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization associated with the connection", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the connection to be toggled", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Connection disabled successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connectionsToggleConnectionResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.connection.disableConnection(organizationId, connectionId);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "scalekit_client.connection.disable_connection(\n organization_id,\n connection_id\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "err := scalekitClient.Connection.DisableConnection(\n ctx,\n organizationId,\n connectionId,\n)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ToggleConnectionResponse response = scalekitClient.connections().disableConnection(connectionId, organizationId);" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/connections/{id}:enable": { + "patch": { + "description": "Activate an existing connection for the specified organization. When enabled, users can authenticate using this connection. This endpoint changes the connection state from disabled to enabled without modifying other configuration settings", + "tags": [ + "Connections" + ], + "summary": "Enable SSO connection", + "operationId": "ConnectionService_EnableConnection", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization associated with the connection", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the connection to be toggled", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Connection enabled successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connectionsToggleConnectionResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.connection.enableConnection(organizationId, connectionId);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "scalekit_client.connection.enable_connection(\n organization_id,\n connection_id,\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "err := scalekitClient.Connection.EnableConnection(\n ctx,\n organizationId,\n connectionId,\n)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ToggleConnectionResponse response = scalekitClient.connections().enableConnection(connectionId, organizationId);" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/directories": { + "get": { + "tags": [ + "Directory" + ], + "summary": "List organization directories", + "operationId": "DirectoryService_ListDirectories", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "organization_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of directories for the organization", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/directoriesListDirectoriesResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.directory.listDirectories('');" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "directories_list = scalekit_client.directory.list_directories(\n\torganization_id=''\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "directories,err := scalekitClient.Directory().ListDirectories(ctx, organizationId)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListDirectoriesResponse response = scalekitClient.directories().listDirectories(organizationId);" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/directories/{directory_id}/groups": { + "get": { + "description": "Retrieves all groups from a specified directory. Use this endpoint to view group structures from your connected identity provider.", + "tags": [ + "Directory" + ], + "summary": "List directory groups", + "operationId": "DirectoryService_ListDirectoryGroups", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the directory", + "name": "directory_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "integer", + "format": "int64" + }, + "description": "Number of groups to return per page. Maximum value is 30. If not specified, defaults to 10", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Token for pagination. Use the value returned in the 'next_page_token' field of the previous response", + "name": "page_token", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "date-time" + }, + "description": "Filter groups updated after this timestamp. Use ISO 8601 format", + "name": "updated_after", + "in": "query" + }, + { + "schema": { + "type": "boolean" + }, + "description": "If true, includes full group details. If false or not specified, returns basic information only", + "name": "include_detail", + "in": "query" + }, + { + "schema": { + "type": "boolean" + }, + "description": "If true, returns group and its details from external provider (default: false)", + "name": "include_external_groups", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of groups from the specified directory", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/directoriesListDirectoryGroupsResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const { groups } = await scalekit.directory.listDirectoryGroups(\n '',\n ''\n);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "directory_groups = scalekit_client.directory.list_directory_groups(\n directory_id='', organization_id=''\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "options := &ListDirectoryGroupsOptions{\n\n\t\tPageSize: 10,\n\n\t\tPageToken:\"\",\n\n\t}\n\n\ndirectoryGroups, err := scalekitClient.Directory().ListDirectoryGroups(ctx, organizationId, directoryId, options)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "var options = ListDirectoryResourceOptions.builder()\n .pageSize(10)\n .pageToken(\"\")\n .includeDetail(true)\n .build();\n\nListDirectoryGroupsResponse groupsResponse = scalekitClient\n .directories()\n .listDirectoryGroups(directory.getId(), organizationId, options);" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/directories/{directory_id}/users": { + "get": { + "description": "Retrieves a list of all users within a specified directory for an organization. This endpoint allows you to view user accounts associated with your connected Directory Providers.", + "tags": [ + "Directory" + ], + "summary": "List directory users", + "operationId": "DirectoryService_ListDirectoryUsers", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the directory within the organization", + "name": "directory_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "integer", + "format": "int64" + }, + "description": "Number of users to return per page. Maximum value is 30. If not specified, defaults to 10", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Token for pagination. Use the value returned in the 'next_page_token' field of the previous response to retrieve the next page of results", + "name": "page_token", + "in": "query" + }, + { + "schema": { + "type": "boolean" + }, + "description": "If set to true, the response will include the full user payload with all available details. If false or not specified, only essential user information will be returned", + "name": "include_detail", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Filter users by their membership in a specific directory group", + "name": "directory_group_id", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "date-time" + }, + "description": "Filter users that were updated after the specified timestamp. Use ISO 8601 format", + "name": "updated_after", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of users from the specified directory", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/directoriesListDirectoryUsersResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const { users } = await scalekit.directory.listDirectoryUsers(\n '',\n ''\n);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "directory_users = scalekit_client.directory.list_directory_users(\n directory_id='', organization_id=''\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "options := &ListDirectoryUsersOptions{\n\n\t\tPageSize: 10,\n\n\t\tPageToken: \"\",\n\n\t}\n\ndirectoryUsers,err := scalekitClient.Directory().ListDirectoryUsers(ctx, organizationId, directoryId, options)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "var options = ListDirectoryResourceOptions.builder()\n .pageSize(10)\n .pageToken(\"\")\n .includeDetail(true)\n .build();\n\nListDirectoryUsersResponse usersResponse = scalekitClient\n .directories()\n .listDirectoryUsers(directory.getId(), organizationId, options);" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/directories/{id}": { + "get": { + "description": "Retrieves detailed information about a specific directory within an organization", + "tags": [ + "Directory" + ], + "summary": "Get directory details", + "operationId": "DirectoryService_GetDirectory", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the directory", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved directory details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/directoriesGetDirectoryResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const { directory } = await scalekit.directory.getDirectory(\n organizationId,\n directoryId\n);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "directory = scalekit_client.directory.get_directory(\n directory_id='', organization_id=''\n)\nprint(f'Directory details: {directory}')" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "directory, err := scalekitClient.Directory().GetDirectory(ctx, organizationId, directoryId)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "Directory directory = scalekitClient.directories().getDirectory(directoryId, organizationId);" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/directories/{id}:disable": { + "patch": { + "description": "Stops synchronization of users and groups from a specified directory within an organization. This operation prevents further updates from the connected Directory provider", + "tags": [ + "Directory" + ], + "summary": "Disable a directory", + "operationId": "DirectoryService_DisableDirectory", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "A unique identifier for the organization. The value must begin with 'org_' and be between 1 and 32 characters long", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "A unique identifier for a directory within the organization. The value must begin with 'dir_' and be between 1 and 32 characters long", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully disabled the directory", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/directoriesToggleDirectoryResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.directory.disableDirectory(\n '',\n ''\n);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "directory_response = scalekit_client.directory.disable_directory(\n directory_id='', organization_id=''\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "disable,err := scalekitClient.Directory().DisableDirectory(ctx, organizationId, directoryId)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ToggleDirectoryResponse disableResponse = scalekitClient\n .directories()\n .disableDirectory(directoryId, organizationId);" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/directories/{id}:enable": { + "patch": { + "description": "Activates a directory within an organization, allowing it to synchronize users and groups with the connected Directory provider", + "tags": [ + "Directory" + ], + "summary": "Enable a directory", + "operationId": "DirectoryService_EnableDirectory", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "A unique identifier for the organization. The value must begin with 'org_' and be between 1 and 32 characters long", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "A unique identifier for a directory within the organization. The value must begin with 'dir_' and be between 1 and 32 characters long", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/directoriesToggleDirectoryResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.directory.enableDirectory('', '');" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "directory_response = scalekit_client.directory.enable_directory(\n directory_id='', organization_id=''\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "enable,err := scalekitClient.Directory().EnableDirectory(ctx, organizationId, directoryId)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ToggleDirectoryResponse enableResponse = client\n .directories()\n .enableDirectory(directoryId, organizationId);" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/domains": { + "get": { + "description": "Retrieves a paginated list of all domains configured for the specified organization.\n\nDomain types:\n- ALLOWED_EMAIL_DOMAIN: Trusted domains used to suggest the organization in the organization switcher during sign-in/sign-up (auth-method agnostic).\n- ORGANIZATION_DOMAIN: SSO discovery domains used to route users to the correct SSO provider and enforce SSO.\n\n", + "tags": [ + "Domains" + ], + "summary": "List Domains", + "operationId": "DomainService_ListDomains", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Scalekit-generated unique identifier for the organization. Use either this or external_id to identify the organization.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Optional comma-separated list of additional fields to include in the response (e.g., 'verification_details').", + "name": "include", + "in": "query" + }, + { + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "Maximum number of domains to return per page. Default is 30, maximum is 100.", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "Page number to retrieve (0-based). Use 0 for the first page.", + "name": "page_number", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "ALLOWED_EMAIL_DOMAIN", + "ORGANIZATION_DOMAIN" + ] + }, + "description": "The domain type.\n- ALLOWED_EMAIL_DOMAIN: trusted domain used to suggest the organization in the organization switcher during sign-in/sign-up.\n- ORGANIZATION_DOMAIN: SSO discovery domain used to route users to the correct SSO provider and enforce SSO.\n", + "name": "domain_type", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of domains.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/domainsListDomainResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "// List all domains in an organization\nconst response = await scalekit.domain.listDomains(organizationId, {\n\tdomainType: \"ORGANIZATION_DOMAIN\"\n});\n\n// Domain object contains:\n// - id: Domain identifier\n// - domain: Domain name\n// - organizationId: Owning organization\n// - domainType: Configuration type" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "# List all domains in an organization\nresponse = scalekit_client.domain.list_domains(\n organization_id=\"org_123\",\n domain_type=\"ORGANIZATION_DOMAIN\"\n )\n# - organization_id: Owning organization\n# - domain_type: domain type" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "domains, err := scalekitClient.Domain().ListDomains(ctx, \"org_id\", &scalekit.ListDomainOptions{\nDomainType: \"ORGANIZATION_DOMAIN\",\n})" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "List domains = scalekitClient.domains().listDomainsByOrganizationId(\"org_id\", \"ORGANIZATION_DOMAIN\");" + } + ] + }, + "post": { + "description": "Creates and associates a domain with an organization.\n\nUse one of the following domain types:\n- ALLOWED_EMAIL_DOMAIN: Adds a trusted email domain for organization suggestions in the organization switcher during sign-in/sign-up (auth-method agnostic).\n- ORGANIZATION_DOMAIN: Enables SSO domain discovery. If a user signs in with a matching email domain, Scalekit redirects them to the organization’s SSO provider and enforces SSO.\n\nThe domain must be a valid business domain that you control. Public/disposable domains (e.g., gmail.com) are blocked for security.\n\n", + "tags": [ + "Domains" + ], + "summary": "Create Domain", + "operationId": "DomainService_CreateDomain", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Scalekit-generated unique identifier for the organization. Use either this or external_id to identify the organization.", + "name": "organization_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully created the domain.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/domainsCreateDomainResponse" + } + } + } + }, + "400": { + "description": "Invalid request — common causes invalid domain format, public or disposable domain, or domain already exists.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/errdetailsErrorInfo" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "// Add a new domain to an organization\nconst response = await scalekit.createDomain(\"org-123\", \"example.com\", {\n\n\t// Domain type: controls user authentication and email validation\n\n\tdomainType: \"ORGANIZATION_DOMAIN\",\n\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "# Add a new domain to an organization\nresponse = scalekit_client.domain.create_domain(organization_id=\"org-123\",\n\n\t\t\tdomain_name=\"example.com\",\n \t\t\tdomain_type=\"ORGANIZATION_DOMAIN\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "domain, err := scalekitClient.Domain().CreateDomain(ctx, \"org_id\", \"example.com\", &scalekit.CreateDomainOptions{\n\n\t\tDomainType: \"ORGANIZATION_DOMAIN\",\n\n\t})" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "CreateDomainRequest request = CreateDomainRequest.newBuilder()\n\t.setOrganizationId(organization.getId())\n\t.setDomain(CreateDomain.newBuilder()\n\t\t.setDomain(\"example.com\")\n\t\t.setDomainType(\"ORGANIZATION_DOMAIN\")\n\t\t.build())\n\t.build();\n\t\nDomain domain = scalekitClient.domains().createDomain(request);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Domain configuration including the domain name and type.", + "$ref": "#/components/schemas/v1domainsCreateDomain" + } + } + }, + "required": true + } + } + }, + "/api/v1/organizations/{organization_id}/domains/{id}": { + "get": { + "description": "Retrieves complete details for a domain including domain type, timestamps, and configuration information.\n\n", + "tags": [ + "Domains" + ], + "summary": "Get Domain", + "operationId": "DomainService_GetDomain", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Scalekit-generated unique identifier for the organization. Use either this or external_id to identify the organization.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Scalekit-generated unique identifier of the domain to retrieve.", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the domain details.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/domainsGetDomainResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "// Fetch details of a specific domain\nconst response = await scalekit.domain.getDomain(organizationId, domainId);\n\n// Domain object properties:\n// - id: Domain identifier\n// - domain: Domain name\n// - organizationId: Owning organization\n// - domainType: Domain configuration type" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "# Fetch details of a specific domain\nresponse = scalekit_client.domain.get_domain(organization_id=\"org_123\", domain_id=\"dom_123\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "domain, err := scalekitClient.Domain().GetDomain(ctx, \"dom_123\", \"org_123\")" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "Domain domain = scalekitClient.domains().getDomainById(\"org_123\", \"dom_123\");" + } + ] + }, + "delete": { + "description": "Permanently removes a domain record from an organization.\n\n- Deleting an ORGANIZATION_DOMAIN disables SSO routing/enforcement for that domain.\n- Deleting an ALLOWED_EMAIL_DOMAIN stops organization suggestions for users with that email domain.\n\n", + "tags": [ + "Domains" + ], + "summary": "Delete Domain", + "operationId": "DomainService_DeleteDomain", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Scalekit-generated unique identifier for the organization. Use either this or external_id to identify the organization.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Scalekit-generated unique identifier of the domain to be permanently deleted.", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Domain successfully deleted.", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "// Remove a domain from an organization\n// Caution: Deletion is permanent and may affect user access\nconst response = await scalekit.domain.deleteDomain(organizationId, domainId);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "# Remove a domain from an organization\n# Caution: Deletion is permanent and may affect user access\nresponse = scalekit_client.domain.delete_domain(\n organization_id=\"org_123\",\n domain_id=\"dom_123\"\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "err = scalekitClient.Domain().DeleteDomain(ctx, \"dom_123\", \"org_123\")" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "scalekitClient.domains().deleteDomain(organization.getId(), domain.getId());" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/settings/usermanagement": { + "patch": { + "description": "Upsert user management settings for an organization", + "tags": [ + "Organizations" + ], + "summary": "Upsert organization user setting", + "operationId": "OrganizationService_UpsertUserManagementSettings", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "ID of the organization.", + "name": "organization_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Returns the updated organization setting.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/organizationsUpsertUserManagementSettingsResponse" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationServiceUpsertUserManagementSettingsBody" + } + } + }, + "required": true + } + } + }, + "/api/v1/organizations/{organization_id}/users": { + "get": { + "description": "Retrieves a paginated list of all users who are members of the specified organization. Use this endpoint to view all users with access to a particular organization, including their roles, metadata, and membership details. Supports pagination for large user lists.", + "tags": [ + "Users" + ], + "summary": "List organization users", + "operationId": "UserService_ListOrganizationUsers", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization for which to list users. Must start with 'org_' and be 1-32 characters long.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "integer", + "format": "int64" + }, + "description": "Maximum number of users to return in a single response. Valid range: 1-100. Server may return fewer users than specified.", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Pagination token from a previous ListUserResponse. Used to retrieve the next page of results. Leave empty for the first request.", + "name": "page_token", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of users in the organization", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersListOrganizationUsersResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const response = await scalekit.user.\n listOrganizationUsers(\"org_123\", {\n\tpageSize: 50,\n});\nconsole.log(response.users);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "resp, _ = scalekit_client.users.list_users(organization_id=\"org_123\", page_size=50)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "list, \n err := scalekitClient.User().ListOrganizationUsers(ctx, \"org_123\", &scalekit.ListUsersOptions{PageSize:\n50}) if err != nil { /* handle error */ }\nfmt.Println(list.Users)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListOrganizationUsersRequest listReq = ListOrganiz\n ationUsersRequest.newBuilder()\n .setPageSize(50)\n .build();\nListOrganizationUsersResponse list = users.\n listOrganizationUsers(\"org_123\", listReq);" + } + ] + }, + "post": { + "description": "Creates a new user account and immediately adds them to the specified organization. Use this endpoint when you want to create a user and grant them access to an organization in a single operation. You can provide user profile information, assign roles, and configure membership metadata. The user receives an activation email unless this feature is disabled in the organization settings.", + "tags": [ + "Users" + ], + "summary": "Create new user in organization", + "operationId": "UserService_CreateUserAndMembership", + "parameters": [ + { + "schema": { + "type": "string" + }, + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "boolean" + }, + "description": "If true, sends an activation email to the user. Defaults to true.", + "name": "send_invitation_email", + "in": "query" + } + ], + "responses": { + "201": { + "description": "User created successfully. Returns the created user object, including system-generated identifiers and timestamps", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersCreateUserAndMembershipResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const {\n user } = await scalekit.user.\n createUserAndMembership(\"org_123\", {\n\temail: \"user@example.com\",\n\texternalId: \"ext_12345a67b89c\",\n\tmetadata: { department: \"engineering\", \n\t location: \"nyc-office\" },\n\tuserProfile: {\n\t\tfirstName: \"John\",\n\t\tlastName: \"Doe\",\n\t},\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "# Create user with membership \nuser = CreateUser(\n email=\"john.doe@example.com\",\n external_id=\"ext_john_123\", # Optional\n user_profile={\n \"first_name\": \"John\",\n \"last_name\": \"Doe\",\n \"name\": \"John Doe\",\n \"locale\": \"en-US\",\n \"phone_number\": \"+14155552671\"\n },\n membership={\n \"roles\": [{\"name\": \"member\"}] \n }\n)\n\n# Create user and membership in organization\nresponse = scalekit_client.users.create_user_and_membership(\n organization_id=\"your_org_id\",\n user=user,\n send_invitation_email=True # Set to False if you don't want to send\nemail )\n\n user_id = response[0].user.id" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "newUser := &usersv1.CreateUser{\n Email: \"user@example.com\",\n ExternalId: \"ext_12345a67b89c\",\n Metadata: map[string]string{\n \"department\": \"engineering\",\n \"location\": \"nyc-office\",\n },\n UserProfile: &usersv1.CreateUserProfile{\n FirstName: \"John\",\n LastName: \"Doe\",\n },\n}\ncuResp, \n err := scalekitClient.User().CreateUserAndMembership(ctx, \"org_123\",\nnewUser, false) if err != nil { /* handle error */ }" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "CreateUser createUser = CreateUser.newBuilder()\n .setEmail(\"user@example.com\")\n .setExternalId(\"ext_12345a67b89c\")\n .putMetadata(\"department\", \"engineering\")\n .putMetadata(\"location\", \"nyc-office\")\n .setUserProfile(\n CreateUserProfile.newBuilder()\n .setFirstName(\"John\")\n .setLastName(\"Doe\")\n .build())\n .build();\nCreateUserAndMembershipRequest cuReq = CreateUserA\n ndMembershipRequest.newBuilder()\n .setUser(createUser)\n .build();\nCreateUserAndMembershipResponse cuResp = users.\n createUserAndMembership(\"org_123\", cuReq);\nSystem.out.println(cuResp.getUser().getId());" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersCreateUser" + } + } + }, + "required": true + } + } + }, + "/api/v1/organizations/{organization_id}/users/{user_id}/permissions": { + "get": { + "description": "Retrieves all permissions a user has access to within a specific organization. This includes permissions from direct role assignments and inherited permissions from role hierarchy.", + "tags": [ + "Users" + ], + "summary": "List user permissions", + "operationId": "UserService_ListUserPermissions", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the organization", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the user", + "name": "user_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of permissions for the user", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersListUserPermissionsResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const { permissions } = await scalekit.user.listUserPermissions(\"org_123\", \"usr_123\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "resp = scalekit_client.users.list_user_permissions(\n organization_id=\"org_123\",\n user_id=\"usr_123\",\n)\npermissions = resp.permissions" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.User().ListUserPermissions(ctx, \"org_123\", \"usr_123\")\nif err != nil {\n // handle error\n}\npermissions := resp.Permissions" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListUserPermissionsResponse resp = scalekitClient.users().listUserPermissions(\"org_123\", \"usr_123\");\nList permissions = resp.getPermissionsList();" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/users/{user_id}/roles": { + "get": { + "description": "Retrieves all roles assigned to a user within a specific organization. This includes both direct role assignments and inherited roles from role hierarchy.", + "tags": [ + "Users" + ], + "summary": "List user roles", + "operationId": "UserService_ListUserRoles", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the organization", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the user", + "name": "user_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of roles assigned to the user", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersListUserRolesResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const { roles } = await scalekit.user.listUserRoles(\"org_123\", \"usr_123\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "resp = scalekit_client.users.list_user_roles(\n organization_id=\"org_123\",\n user_id=\"usr_123\",\n)\nroles = resp.roles" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.User().ListUserRoles(ctx, \"org_123\", \"usr_123\")\nif err != nil {\n // handle error\n}\nroles := resp.Roles" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListUserRolesResponse resp = scalekitClient.users().listUserRoles(\"org_123\", \"usr_123\");\nList roles = resp.getRolesList();" + } + ] + } + }, + "/api/v1/organizations/{organization_id}/users:search": { + "get": { + "description": "Searches for users within a specific organization by email address, user ID, or external ID. The query must be at least 3 characters and is case-insensitive. Scopes results strictly to the given organization. Returns a paginated list of matching users with up to 30 results per page. Use the next_page_token from the response to retrieve subsequent pages.", + "tags": [ + "Users" + ], + "summary": "Search organization users", + "operationId": "UserService_SearchOrganizationUsers", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier of the organization to search within. Must start with 'org_' and be 1-32 characters long.", + "name": "organization_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string", + "minLength": 3, + "maxLength": 100 + }, + "description": "Search term to match against user email, IDs, or external IDs. Must be at least 3 characters. Case insensitive.", + "name": "query", + "in": "query", + "required": true + }, + { + "schema": { + "type": "integer", + "format": "int64", + "minimum": 1, + "maximum": 30 + }, + "description": "Maximum number of users to return per page. Value must be between 1 and 30.", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Token from a previous response for pagination. Provide this to retrieve the next page of results.", + "name": "page_token", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Matching users within the organization returned; includes pagination cursors for navigating large result sets.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersSearchOrganizationUsersResponse" + } + } + } + }, + "400": { + "description": "Bad Request - query must be at least 3 characters and no more than 100 characters, and organization_id must be a valid org_ prefixed identifier.", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Not Found - organization not found.", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, + "/api/v1/organizations:external/{external_id}": { + "get": { + "description": "Retrieves organization details by External ID, including name, region, metadata, and settings", + "tags": [ + "Organizations" + ], + "summary": "Get organization details by external Id", + "operationId": "OrganizationService_GetOrganizationByExternalId", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier that links an Organization Object to your app's tenant, stored as an External ID", + "name": "external_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Unique scalekit-generated identifier that uniquely references an organization", + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Returns the complete organization object with ID, display name, settings, external ID and metadata", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/organizationsGetOrganizationResponse" + } + } + } + }, + "400": { + "description": "Invalid request - external ID is empty or the caller's organization claim does not match", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Organization not found - no organization exists with the specified external ID", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, + "/api/v1/passwordless/email/resend": { + "post": { + "description": "Resend a verification email if the user didn't receive it or if the previous code/link has expired", + "tags": [ + "Magic link & OTP" + ], + "summary": "Resend passwordless email", + "operationId": "PasswordlessService_ResendPasswordlessEmail", + "responses": { + "200": { + "description": "Successfully resent the passwordless authentication email. Returns updated authentication request details with new expiration time.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/passwordlessSendPasswordlessResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const { authRequestId } = sendResponse;\nconst resendResponse = await scalekit.passwordless.resendPasswordlessEmail(\n\n\tauthRequestId\n\n);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "resend_response = scalekit_client.passwordless.resend_passwordless_email(\n auth_request_id=auth_request_id,\n)\n\n# New auth request ID from resend\nnew_auth_request_id = resend_response[0].auth_request_id" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resendResponse, err := scalekitClient.Passwordless().ResendPasswordlessEmail(\n ctx,\n authRequestId,\n)\n\nif err != nil {\n // Handle error\n return\n}" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "SendPasswordlessResponse resendResponse = passwordlessClient.resendPasswordlessEmail(authRequestId);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/passwordlessResendPasswordlessRequest" + } + } + }, + "required": true + } + } + }, + "/api/v1/passwordless/email/send": { + "post": { + "description": "Send a verification email containing either a verification code (OTP), magic link, or both to a user's email address", + "tags": [ + "Magic link & OTP" + ], + "summary": "Send passwordless email", + "operationId": "PasswordlessService_SendPasswordlessEmail", + "responses": { + "200": { + "description": "Successfully sent passwordless authentication email. Returns the authentication request details including expiration time and auth request ID", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/passwordlessSendPasswordlessResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const response = await scalekit.passwordless.sendPasswordlessEmail(\n\t\"john.doe@example.com\",\n\t{\n\t\ttemplate: \"SIGNIN\",\n\t\texpiresIn: 100,\n\t\tmagiclinkAuthUri: \"https://www.google.com\",\n\t\ttemplateVariables: {\n\t\t\temployeeID: \"EMP523\",\n\t\t\tteamName: \"Alpha Team\",\n\t\t\tsupportEmail: \"support@yourcompany.com\",\n\t\t},\n\t}\n);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "response = scalekit_client.passwordless.send_passwordless_email(\n email=\"john.doe@example.com\",\n template=\"SIGNIN\", # or \"SIGNUP\", \"UNSPECIFIED\"\n expires_in=100,\n magiclink_auth_uri=\"https://www.google.com\",\n template_variables={\n \"employeeID\": \"EMP523\",\n \"teamName\": \"Alpha Team\",\n \"supportEmail\": \"support@yourcompany.com\",\n },\n)\n\n# Extract auth request ID from response\nauth_request_id = response[0].auth_request_id" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "templateType := scalekit.TemplateTypeSignin\nresponse, err := scalekitClient.Passwordless().SendPasswordlessEmail(\n ctx,\n \"john.doe@example.com\",\n &scalekit.SendPasswordlessOptions{\n Template: &templateType,\n ExpiresIn: 100,\n MagiclinkAuthUri: \"https://www.google.com\",\n TemplateVariables: map[string]string{\n \"employeeID\": \"EMP523\",\n \"teamName\": \"Alpha Team\",\n \"supportEmail\": \"support@yourcompany.com\",\n },\n },\n)\n\nif err != nil {\n // Handle error\n return\n}\n\nauthRequestId := response.AuthRequestId" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "TemplateType templateType = TemplateType.SIGNIN;\nMap templateVariables = new HashMap<>();\ntemplateVariables.put(\"employeeID\", \"EMP523\");\ntemplateVariables.put(\"teamName\", \"Alpha Team\");\ntemplateVariables.put(\"supportEmail\", \"support@yourcompany.com\");\n\nSendPasswordlessOptions options = new SendPasswordlessOptions();\noptions.setTemplate(templateType);\noptions.setExpiresIn(100);\noptions.setMagiclinkAuthUri(\"https://www.example.com\");\noptions.setTemplateVariables(templateVariables);\n\nSendPasswordlessResponse response = passwordlessClient.sendPasswordlessEmail(\n \"john.doe@example.com\",\n options\n);\n\nString authRequestId = response.getAuthRequestId();" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/passwordlessSendPasswordlessRequest" + } + } + }, + "required": true + } + } + }, + "/api/v1/passwordless/email/verify": { + "post": { + "description": "Verify a user's identity using either a verification code or magic link token", + "tags": [ + "Magic link & OTP" + ], + "summary": "Verify passwordless email", + "operationId": "PasswordlessService_VerifyPasswordlessEmail", + "responses": { + "200": { + "description": "Successfully verified the passwordless authentication. Returns user email", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/passwordlessVerifyPasswordLessResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const { authRequestId } = sendResponse;\nconst verifyResponse = await scalekit.passwordless.verifyPasswordlessEmail(\n\n\t// Verification Code (OTP)\n\n\t{ code: \"123456\" },\n\n\t// Magic Link Token\n\n\t{ linkToken: link_token },\n\n\tauthRequestId\n\n);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "# Verify with OTP code\nverify_response = scalekit_client.passwordless.verify_passwordless_email(\n code=\"123456\", # OTP code received via email\n auth_request_id=auth_request_id,\n)\n\n# Verify with magic link token\nverify_response = scalekit_client.passwordless.verify_passwordless_email(\n link_token=link_token, # Magic link token from URL\n)\n\n# User verified successfully\nuser_email = verify_response[0].email" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "// Verify with OTP code\nverifyResponse, err := scalekitClient.Passwordless().VerifyPasswordlessEmail(\n ctx,\n &scalekit.VerifyPasswordlessOptions{\n Code: \"123456\", // OTP code\n AuthRequestId: authRequestId,\n },\n)\n\nif err != nil {\n // Handle error\n return\n}\n\n// Verify with magic link token\nverifyResponse, err := scalekitClient.Passwordless().VerifyPasswordlessEmail(\n ctx,\n &scalekit.VerifyPasswordlessOptions{\n LinkToken: linkToken, // Magic link token\n },\n)\n\nif err != nil {\n // Handle error\n return\n}\n\n// User verified successfully\nuserEmail := verifyResponse.Email" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "// Verify with OTP code\nVerifyPasswordlessOptions verifyOptions = new VerifyPasswordlessOptions();\nverifyOptions.setCode(\"123456\"); // OTP code\nverifyOptions.setAuthRequestId(authRequestId);\n\nVerifyPasswordLessResponse verifyResponse = passwordlessClient.verifyPasswordlessEmail(verifyOptions);\n\n// User verified successfully\nString userEmail = verifyResponse.getEmail();\n\n// Verify with magic link token\nVerifyPasswordlessOptions verifyOptions = new VerifyPasswordlessOptions();\nverifyOptions.setLinkToken(linkToken); // Magic link token\n\nVerifyPasswordLessResponse verifyResponse = passwordlessClient.verifyPasswordlessEmail(verifyOptions);\n\n// User verified successfully\nString userEmail = verifyResponse.getEmail();" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/passwordlessVerifyPasswordLessRequest" + } + } + }, + "required": true + } + } + }, + "/api/v1/permissions": { + "get": { + "description": "Retrieves a comprehensive, paginated list of all permissions available within the environment. Use this endpoint to view all permission definitions for auditing, role management, or understanding the complete set of available access controls. The response includes pagination tokens to navigate through large sets of permissions efficiently. Each permission object contains the permission name, description, creation time, and last update time. This operation is useful for building permission selection interfaces, auditing permission usage, or understanding the scope of available access controls in your RBAC system.", + "tags": [ + "Permissions" + ], + "summary": "List all permissions", + "operationId": "RolesService_ListPermissions", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Page token to retrieve next page of results", + "name": "page_token", + "in": "query" + }, + { + "schema": { + "type": "integer", + "format": "int64" + }, + "description": "Number of permissions to return per page (max 100)", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string", + "enum": [ + "SCALEKIT", + "ENVIRONMENT" + ] + }, + "description": "Filter permissions by type: ALL, SCALEKIT, or ENVIRONMENT, where SCALEKIT are predefined Scalekit permissions and ENVIRONMENT are custom permissions created in the environment, default is ALL", + "name": "type", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of permissions. Returns a paginated list of permission objects with metadata and pagination tokens for navigation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesListPermissionsResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.permission.listPermissions();" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.permissions.list_permissions()" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Permission().ListPermissions(ctx)\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListPermissionsResponse res = scalekitClient.permissions().listPermissions();" + } + ] + }, + "post": { + "description": "Creates a new permission that represents a specific action users can perform within the environment. Use this endpoint to define granular access controls for your RBAC system. You can provide a unique permission name following the format 'action:resource' (for example, 'read:documents', 'write:users') and an optional description explaining the permission's purpose. The permission name must be unique across the environment and follows alphanumeric naming conventions with colons and underscores. Returns the created permission object including system-generated ID and timestamps.", + "tags": [ + "Permissions" + ], + "summary": "Create new permission", + "operationId": "RolesService_CreatePermission", + "responses": { + "201": { + "description": "Permission created successfully. Returns the complete permission object with system-generated ID, name, description, and timestamps.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesCreatePermissionResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.permission.createPermission({\n name: \"read:users\",\n description: \"Allows reading users\"\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "from scalekit.v1.roles.roles_pb2 import CreatePermission\n\npermission = CreatePermission(\n name=\"read:users\",\n description=\"Allows reading users\"\n)\n\nscalekit_client.permissions.create_permission(permission=permission)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Permission().CreatePermission(ctx, &rolesv1.CreatePermission{\n\n\tName: \"read:users\",\n\n\tDescription: \"Allows reading users\",\n\n})\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "CreatePermissionResponse res = scalekitClient.permissions().createPermission(\n CreatePermissionRequest.newBuilder()\n .setPermission(\n CreatePermission.newBuilder()\n .setName(\"read:users\")\n .setDescription(\"Allows reading users\")\n .build()\n )\n .build()\n);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/v1rolesCreatePermission" + } + } + }, + "required": true + } + } + }, + "/api/v1/permissions/{permission_name}": { + "get": { + "description": "Retrieves complete information for a specific permission by its unique name identifier. Use this endpoint to view permission details including description, creation time, and last update time. Provide the permission name in the path parameter following the format 'action:resource' (for example, 'read:documents'). This operation is useful for auditing permission definitions, understanding permission purposes, or verifying permission existence before assignment. Returns the complete permission object with all metadata and system-generated timestamps.", + "tags": [ + "Permissions" + ], + "summary": "Retrieve permission details", + "operationId": "RolesService_GetPermission", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Name of the permission", + "name": "permission_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved permission details. Returns the complete permission object including name, description, creation time, and update time.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesGetPermissionResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.permission.getPermission(\"read:users\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.permissions.get_permission(\n permission_name=\"read:users\"\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Permission().GetPermission(ctx, \"read:users\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "GetPermissionResponse res = scalekitClient.permissions().getPermission(\"read:users\");" + } + ] + }, + "put": { + "description": "Modifies an existing permission's attributes including description and metadata. Use this endpoint to update permission descriptions or clarify permission purposes after creation. The permission is identified by its unique name in the path parameter, and only the fields you specify in the request body will be updated. Note that the permission name itself cannot be changed as it serves as the immutable identifier. This operation is useful for maintaining clear documentation of permission purposes or updating descriptions to reflect changes in system functionality. Returns the updated permission object with modified timestamps.", + "tags": [ + "Permissions" + ], + "summary": "Update permission details", + "operationId": "RolesService_UpdatePermission", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Name of the permission", + "name": "permission_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Permission updated successfully. Returns the modified permission object with updated description and timestamps.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesUpdatePermissionResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.permission.updatePermission(\"read:users\", {\n name: \"read:users\",\n description: \"Allows reading user resources\"\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "from scalekit.v1.roles.roles_pb2 import CreatePermission\n\nscalekit_client.permissions.update_permission(\n permission_name=\"read:users\",\n permission=CreatePermission(\n name=\"read:users\",\n description=\"Allows reading user resources\"\n )\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Permission().UpdatePermission(ctx, \"read:users\", &rolesv1.CreatePermission{\n Name: \"read:users\",\n Description: \"Allows reading user resources\",\n})\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "UpdatePermissionResponse res = scalekitClient.permissions().updatePermission(\n \"read:users\",\n UpdatePermissionRequest.newBuilder()\n .setPermission(\n CreatePermission.newBuilder()\n .setName(\"read:users\")\n .setDescription(\"Allows reading user resources\")\n .build()\n )\n .build()\n);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/v1rolesCreatePermission" + } + } + }, + "required": true + } + }, + "delete": { + "description": "Permanently removes a permission from the environment using its unique name identifier. Use this endpoint when you need to clean up unused permissions or remove access controls that are no longer relevant. The permission is identified by its name in the path parameter following the format 'action:resource'. This operation cannot be undone, so ensure no active roles depend on the permission before deletion. If the permission is currently assigned to any roles, you may need to remove those assignments first or update the roles to use alternative permissions. Returns no content on successful deletion.", + "tags": [ + "Permissions" + ], + "summary": "Delete permission", + "operationId": "RolesService_DeletePermission", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Name of the permission", + "name": "permission_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Permission successfully deleted. No content returned.", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.permission.deletePermission(\"read:users\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "scalekit_client.permissions.delete_permission(\n permission_name=\"read:users\"\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "err := scalekitClient.Permission().DeletePermission(ctx, \"read:users\")\nif err != nil { /* handle err */ }" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "scalekitClient.permissions().deletePermission(\"read:users\");" + } + ] + } + }, + "/api/v1/roles": { + "get": { + "description": "Retrieves a comprehensive list of all roles available within the specified environment including organization roles. Use this endpoint to view all role definitions, including custom roles and their configurations. You can optionally include permission details for each role to understand their capabilities. This is useful for role management, auditing organization access controls, or understanding the available access levels within the organization.", + "tags": [ + "Roles" + ], + "summary": "List all roles in environment", + "operationId": "RolesService_ListRoles", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Include additional data in the response. Valid values: 'permissions' (direct permissions only), 'permissions:all' (includes inherited permissions from role hierarchy)", + "name": "include", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved list of roles. Returns all roles with their metadata and optionally their permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesListRolesResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.role.listRoles();" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.roles.list_roles()" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().ListRoles(ctx)\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListRolesResponse res = scalekitClient.roles().listRoles();" + } + ] + }, + "post": { + "description": "Creates a new role within the environment with specified permissions and metadata. Use this endpoint to define custom roles that can be assigned to users or groups. You can create hierarchical roles by extending existing roles, assign specific permissions, and configure display information. Roles are the foundation of your access control system and determine what actions users can perform.", + "tags": [ + "Roles" + ], + "summary": "Create new role in environment", + "operationId": "RolesService_CreateRole", + "responses": { + "201": { + "description": "Role created successfully. Returns the complete role object with system-generated ID and timestamps.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesCreateRoleResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.role.createRole({\n name: \"admin\",\n displayName: \"Admin\",\n description: \"Environment-level role\",\n extends: \"base_role\", // optional\n permissions: [\"read:users\"] // optional\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "from scalekit.v1.roles.roles_pb2 import CreateRole\n\nrole = CreateRole(\n name=\"admin\",\n display_name=\"Admin\",\n description=\"Environment-level role\",\n extends=\"base_role\", # optional\n permissions=[\"read:users\"] # optional\n)\n\nscalekit_client.roles.create_role(role=role)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().CreateRole(ctx, &rolesv1.CreateRole{\n\n\tName: \"admin\",\n\n\tDisplayName: \"Admin\",\n\n\tDescription: \"Environment-level role\",\n\n\tExtends: proto.String(\"base_role\"), // optional\n\n\tPermissions: []string{\"read:users\"}, // optional\n\n})" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "CreateRoleResponse res = scalekitClient.roles().createRole(\n CreateRoleRequest.newBuilder()\n .setRole(\n CreateRole.newBuilder()\n .setName(\"admin\")\n .setDisplayName(\"Admin\")\n .setDescription(\"Environment-level role\")\n // .setExtends(\"base_role\") // optional\n // .addPermissions(\"read:users\") // optional\n .build()\n )\n .build()\n);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Role configuration details including name, display name, description, permissions, and inheritance settings.", + "$ref": "#/components/schemas/v1rolesCreateRole", + "examples": [ + { + "description": "Can edit content", + "display_name": "Content Editor", + "name": "content_editor", + "permissions": [ + "read:content", + "write:content" + ] + } + ] + } + } + }, + "required": true + } + } + }, + "/api/v1/roles/default": { + "patch": { + "description": "Updates the default creator and member roles for the current environment. Use this endpoint to configure which roles are automatically assigned to new users when they join the environment. You can specify role names for both creator and member default roles. The system will validate that the specified roles exist and update the environment settings accordingly. Returns the updated default role objects including their complete role information and permissions.", + "tags": [ + "Roles" + ], + "summary": "Set default creator and member roles", + "operationId": "RolesService_UpdateDefaultRoles2", + "responses": { + "200": { + "description": "Default roles updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesUpdateDefaultRolesResponse" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesUpdateDefaultRolesRequest" + } + } + }, + "required": true + } + } + }, + "/api/v1/roles/{role_name}": { + "get": { + "description": "Retrieves complete information for a specific role including metadata and inheritance details (base role and dependent role count). Use this endpoint to audit role configuration and understand the role's place in the hierarchy. To view the role's permissions, use the ListRolePermissions endpoint.", + "tags": [ + "Roles" + ], + "summary": "Get role details", + "operationId": "RolesService_GetRole", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique name identifier of the role to retrieve. Must be alphanumeric with underscores, 1-64 characters.", + "name": "role_name", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Include additional data in the response. Valid values: 'permissions' (direct permissions only), 'permissions:all' (includes inherited permissions from role hierarchy)", + "name": "include", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved role details. Returns the role object including metadata and inheritance details. Permissions are not included.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesGetRoleResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.role.getRole(\"admin\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.roles.get_role(role_name=\"admin\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().GetRole(ctx, \"admin\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "GetRoleResponse res = scalekitClient.roles().getRole(\"admin\");" + } + ] + }, + "put": { + "description": "Modifies an existing role's properties including display name, description, permissions, and inheritance. Use this endpoint to update role metadata, change permission assignments, or modify role hierarchy. Only the fields you specify will be updated, leaving other properties unchanged. When updating permissions, the new list replaces all existing permissions for the role.", + "tags": [ + "Roles" + ], + "summary": "Update role information", + "operationId": "RolesService_UpdateRole", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique name identifier of the role to update. Must be alphanumeric with underscores, 1-64 characters.", + "name": "role_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Role updated successfully. Returns the modified role object with updated timestamps.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesUpdateRoleResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.role.updateRole(\"admin\", {\n displayName: \"Admin (Updated)\",\n description: \"Updated description\"\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "from scalekit.v1.roles.roles_pb2 import UpdateRole\n\nscalekit_client.roles.update_role(\n role_name=\"admin\",\n role=UpdateRole(\n display_name=\"Admin (Updated)\",\n description=\"Updated description\"\n )\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().UpdateRole(ctx, \"admin\", &rolesv1.UpdateRole{\n DisplayName: \"Admin (Updated)\",\n Description: \"Updated description\",\n})\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "UpdateRoleResponse res = scalekitClient.roles().updateRole(\n \"admin\",\n UpdateRoleRequest.newBuilder()\n .setRole(\n UpdateRole.newBuilder()\n .setDisplayName(\"Admin (Updated)\")\n .setDescription(\"Updated description\")\n .build()\n )\n .build()\n);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "Role fields to update. Only specified fields will be modified.", + "$ref": "#/components/schemas/v1rolesUpdateRole", + "examples": [ + { + "description": "Can edit and approve content", + "display_name": "Senior Editor" + } + ] + } + } + }, + "required": true + } + }, + "delete": { + "description": "Permanently removes a role from the environment and reassigns users who had that role to a different role. Use this endpoint when you need to clean up unused roles or restructure your access control system. The role cannot be deleted if it has dependent roles (roles that extend it) unless you specify a replacement role. If users are assigned to the role being deleted, you must provide a reassign_role_name to move those users to a different role before deletion can proceed. This action cannot be undone, so ensure no critical users depend on the role before deletion.", + "tags": [ + "Roles" + ], + "summary": "Delete role and reassign users", + "operationId": "RolesService_DeleteRole", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique name identifier of the role to delete. Must be alphanumeric with underscores, 1-64 characters.", + "name": "role_name", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Role name to reassign users to when deleting this role", + "name": "reassign_role_id", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Role name to reassign users to when deleting this role", + "name": "reassign_role_name", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Role successfully deleted and users reassigned. No content returned.", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "// Basic delete\nawait scalekit.role.deleteRole(\"admin\");\n\n// With reassignment\nawait scalekit.role.deleteRole(\"admin\", \"member\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "# Basic delete\nscalekit_client.roles.delete_role(role_name=\"admin\")\n\n# With reassignment\nscalekit_client.roles.delete_role(\n role_name=\"admin\",\n reassign_role_name=\"member\"\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "// Basic delete\nerr := scalekitClient.Role().DeleteRole(ctx, \"admin\")\nif err != nil { /* handle err */ }\n\n// With reassignment\nerr = scalekitClient.Role().DeleteRole(ctx, \"admin\", \"member\")" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "// Basic delete\nscalekitClient.roles().deleteRole(\"admin\");\n\n// With reassignment\nscalekitClient.roles().deleteRole(\"admin\", \"member\");" + } + ] + } + }, + "/api/v1/roles/{role_name}/base": { + "delete": { + "description": "Removes the base role inheritance relationship for a specified role, effectively eliminating all inherited permissions from the base role. Use this endpoint when you want to break the hierarchical relationship between roles and remove inherited permissions. The role will retain only its directly assigned permissions after this operation. This action cannot be undone, so ensure the role has sufficient direct permissions before removing inheritance. Returns no content on successful removal of the base relationship.", + "tags": [ + "Roles" + ], + "summary": "Delete role inheritance relationship", + "operationId": "RolesService_DeleteRoleBase", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique name identifier of the role whose base inheritance relationship should be removed. Must be alphanumeric with underscores, 1-64 characters.", + "name": "role_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Base role inheritance relationship successfully removed. The role now has only its directly assigned permissions.", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.role.deleteRoleBase(\"senior_editor\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "scalekit_client.roles.delete_role_base(role_name=\"senior_editor\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "err := scalekitClient.Role().DeleteRoleBase(ctx, \"senior_editor\")\nif err != nil {\n // handle error\n}" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "scalekitClient.roles().deleteRoleBase(\"senior_editor\");" + } + ] + } + }, + "/api/v1/roles/{role_name}/dependents": { + "get": { + "description": "Retrieves all roles that directly extend the specified base role through inheritance. Use this endpoint to understand the role hierarchy and identify which roles inherit permissions from a particular base role. Provide the base role name as a path parameter, and the response will include all dependent roles with their metadata and permission information. This operation is useful for auditing role inheritance relationships, understanding the impact of changes to base roles, or managing role hierarchies effectively. Returns a list of dependent role objects including their names, display names, descriptions, and permission details.", + "tags": [ + "Roles" + ], + "summary": "List dependent roles", + "operationId": "RolesService_ListDependentRoles", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Name of the base role", + "name": "role_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved dependent roles. Returns a list of all roles that extend the specified base role, including their metadata and permission information.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesListDependentRolesResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.role.listDependentRoles(\"admin\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.roles.list_dependent_roles(role_name=\"admin\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().ListDependentRoles(ctx, \"admin\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListDependentRolesResponse res = scalekitClient.roles().listDependentRoles(\"admin\");" + } + ] + } + }, + "/api/v1/roles/{role_name}/permissions": { + "get": { + "description": "Retrieves all permissions directly assigned to the specified role, excluding permissions inherited from base roles. Use this endpoint to view the explicit permission assignments for a role, which is useful for understanding direct role capabilities, auditing permission assignments, or managing role-permission relationships. Provide the role name as a path parameter, and the response will include only the permissions that are directly assigned to that role. This operation does not include inherited permissions from role hierarchies - use ListEffectiveRolePermissions to see the complete set of permissions including inheritance. Returns a list of permission objects with their names, descriptions, and assignment metadata.", + "tags": [ + "Roles" + ], + "summary": "List permissions for role", + "operationId": "RolesService_ListRolePermissions", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Name of the role", + "name": "role_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved role permissions. Returns a list of all permissions directly assigned to the specified role, excluding inherited permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesListRolePermissionsResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.permission.listRolePermissions(\"admin\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.permissions.list_role_permissions(role_name=\"admin\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Permission().ListRolePermissions(ctx, \"admin\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListRolePermissionsResponse res = scalekitClient.permissions().listRolePermissions(\"admin\");" + } + ] + }, + "post": { + "description": "Adds one or more permissions to the specified role while preserving existing permission assignments. Use this endpoint to grant additional capabilities to a role without affecting its current permission set. Provide the role name as a path parameter and a list of permission names in the request body. The system will validate that all specified permissions exist in the environment and add them to the role. Existing permission assignments remain unchanged, making this operation safe for incremental permission management. This is useful for gradually expanding role capabilities or adding new permissions as your system evolves. Returns the updated list of all permissions now assigned to the role.", + "tags": [ + "Roles" + ], + "summary": "Add permissions to role", + "operationId": "RolesService_AddPermissionsToRole", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Name of the role", + "name": "role_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Permissions added to role successfully. Returns the complete list of all permissions now assigned to the role, including both existing and newly added permissions.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesAddPermissionsToRoleResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.permission.addPermissionsToRole(\"role_admin\", [\"perm.read\", \"perm.write\"]);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "scalekit_client.permissions.add_permissions_to_role(\n role_name=\"role_admin\",\n permission_names=[\"perm.read\", \"perm.write\"]\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Permission().AddPermissionsToRole(ctx, \"role_admin\", []string{\"perm.read\", \"perm.write\"})" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "AddPermissionsToRoleResponse res = scalekitClient.permissions().addPermissionsToRole(\n \"role_admin\",\n AddPermissionsToRoleRequest.newBuilder()\n .addPermissionNames(\"perm.read\")\n .addPermissionNames(\"perm.write\")\n .build()\n);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RolesServiceAddPermissionsToRoleBody" + } + } + }, + "required": true + } + } + }, + "/api/v1/roles/{role_name}/permissions/{permission_name}": { + "delete": { + "description": "Removes a specific permission from the specified role, revoking that capability from all users assigned to the role. Use this endpoint to restrict role capabilities or remove unnecessary permissions. Provide both the role name and permission name as path parameters. This operation only affects the direct permission assignment and does not impact permissions inherited from base roles. If the permission is inherited through role hierarchy, you may need to modify the base role instead. This is useful for fine-tuning role permissions, implementing least-privilege access controls, or removing deprecated permissions. Returns no content on successful removal.", + "tags": [ + "Roles" + ], + "summary": "Remove permission from role", + "operationId": "RolesService_RemovePermissionFromRole", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Name of the role", + "name": "role_name", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Name of the permission to remove", + "name": "permission_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Permission removed from role successfully. No content returned.", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.permission.removePermissionFromRole(\"admin\", \"read:users\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "scalekit_client.permissions.remove_permission_from_role(\n role_name=\"admin\",\n permission_name=\"read:users\"\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "err := scalekitClient.Permission().RemovePermissionFromRole(ctx, \"admin\", \"read:users\")\nif err != nil { /* handle err */ }" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "scalekitClient.permissions().removePermissionFromRole(\"admin\", \"read:users\");" + } + ] + } + }, + "/api/v1/roles/{role_name}/permissions:all": { + "get": { + "description": "Retrieves the complete set of effective permissions for a role, including both directly assigned permissions and permissions inherited from base roles through the role hierarchy. Use this endpoint to understand the full scope of capabilities available to users assigned to a specific role. Provide the role name as a path parameter, and the response will include all permissions that apply to the role, accounting for inheritance relationships. This operation is essential for auditing role capabilities, understanding permission inheritance, or verifying the complete access scope before role assignment. Returns a comprehensive list of permission names representing the full set of effective permissions for the specified role.", + "tags": [ + "Roles" + ], + "summary": "List effective permissions for role", + "operationId": "RolesService_ListEffectiveRolePermissions", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Name of the role", + "name": "role_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved effective permissions. Returns the complete list of all permissions that apply to the role, including both direct assignments and inherited permissions from base roles.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesListEffectiveRolePermissionsResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const { permissions } = await scalekit.permission.listEffectiveRolePermissions(\"senior_editor\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "response = scalekit_client.permissions.list_effective_role_permissions(role_name=\"senior_editor\")\npermissions = response.permissions" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Permission().ListEffectiveRolePermissions(ctx, \"senior_editor\")\nif err != nil {\n // handle error\n}\npermissions := resp.Permissions" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListEffectiveRolePermissionsResponse response = scalekitClient.permissions().listEffectiveRolePermissions(\"senior_editor\");\nList permissions = response.getPermissionsList();" + } + ] + } + }, + "/api/v1/roles/{role_name}/users:count": { + "get": { + "description": "Retrieves the total number of users currently assigned to the specified role within the environment. Use this endpoint to monitor role usage, enforce user limits, or understand the scope of role assignments. Provide the role's unique name as a path parameter, and the response will include the current user count for that role. This operation is read-only and does not modify any data or user assignments. The count reflects all users who have the role either directly assigned or inherited through organization membership. This information is useful for capacity planning, security auditing, or understanding the impact of role changes across your user base.", + "tags": [ + "Roles" + ], + "summary": "Retrieve user count for role", + "operationId": "RolesService_GetRoleUsersCount", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique name of the role", + "name": "role_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved user count for the specified role. Returns the total number of users currently assigned to the role, including both direct assignments and inherited assignments.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesGetRoleUsersCountResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.role.getRoleUsersCount(\"admin\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.roles.get_role_users_count(role_name=\"admin\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().GetRoleUsersCount(ctx, \"admin\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "GetRoleUsersCountResponse res = scalekitClient.roles().getRoleUsersCount(\"admin\");" + } + ] + } + }, + "/api/v1/roles:set_defaults": { + "patch": { + "description": "Updates the default creator and member roles for the current environment. Use this endpoint to configure which roles are automatically assigned to new users when they join the environment. You can specify role names for both creator and member default roles. The system will validate that the specified roles exist and update the environment settings accordingly. Returns the updated default role objects including their complete role information and permissions.", + "tags": [ + "Roles" + ], + "summary": "Set default creator and member roles", + "operationId": "RolesService_UpdateDefaultRoles", + "responses": { + "200": { + "description": "Default roles updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesUpdateDefaultRolesResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.role.updateDefaultRoles({\n defaultMemberRole: \"member\"\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "from scalekit.v1.roles.roles_pb2 import UpdateDefaultRolesRequest\n\nres = scalekit_client.roles.update_default_roles(\n default_roles=UpdateDefaultRolesRequest(\n default_member_role=\"member\"\n )\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Role().UpdateDefaultRoles(ctx, \"member\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "UpdateDefaultRolesResponse res = scalekitClient.roles().updateDefaultRoles(\n UpdateDefaultRolesRequest.newBuilder()\n .setDefaultMemberRole(\"member\")\n .build()\n);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rolesUpdateDefaultRolesRequest" + } + } + }, + "required": true + } + } + }, + "/api/v1/sessions/{session_id}": { + "get": { + "description": "Retrieves comprehensive details for a specific user session including authentication status, device information, and expiration timelines. Use this endpoint to fetch current session metadata for security audits, session validation, or to display session information in user account management interfaces. Returns all session properties including the user ID, authenticated organizations, device details with browser/OS information, IP address and geolocation, and all relevant timestamps (creation, last activity, idle expiration, absolute expiration, and actual expiration if applicable).", + "tags": [ + "Sessions" + ], + "summary": "Get session details", + "operationId": "SessionService_GetSession", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the session. Must start with 'ses_' prefix.", + "name": "session_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved session details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/sessionsSessionDetails" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.session.getSession(\"ses_123456789\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.sessions.get_session(session_id=\"ses_123456789\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Session().GetSession(ctx, \"ses_123456789\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "SessionDetails res = scalekitClient.sessions().getSession(\"ses_123456789\");" + } + ] + } + }, + "/api/v1/sessions/{session_id}/revoke": { + "post": { + "description": "Immediately invalidates a specific user session by session ID, setting its status to 'revoked'. Once revoked, the session cannot be used for any future API requests or application access. Use this endpoint to implement session-level logout, force a user to reauthenticate on a specific device, or terminate suspicious sessions. The revocation is instantaneous and irreversible. Returns the revoked session details including the session ID, user ID, and the revocation timestamp.", + "tags": [ + "Sessions" + ], + "summary": "Revoke user session", + "operationId": "SessionService_RevokeSession", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the session to revoke. Must start with 'ses_' prefix.", + "name": "session_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully revoked the session. Returns the revoked session details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/sessionsRevokeSessionResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.session.revokeSession(\"ses_123456789\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.sessions.revoke_session(session_id=\"ses_123456789\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Session().RevokeSession(ctx, \"ses_123456789\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "RevokeSessionResponse res = scalekitClient.sessions().revokeSession(\"ses_123456789\");" + } + ] + } + }, + "/api/v1/users": { + "get": { + "description": "Retrieves a paginated list of all users across your entire environment. Use this endpoint to view all users regardless of their organization memberships. This is useful for administrative purposes, user audits, or when you need to see all users in your Scalekit environment. Supports pagination for large user bases.", + "tags": [ + "Users" + ], + "summary": "List all users in environment", + "operationId": "UserService_ListUsers", + "parameters": [ + { + "schema": { + "type": "integer", + "format": "int64" + }, + "description": "Maximum number of organizations to return per page. Must be between 10 and 100", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Pagination token from the previous response. Use to retrieve the next page of organizations", + "name": "page_token", + "in": "query" + } + ], + "responses": { + "200": { + "description": "List of users.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersListUsersResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const response = await scalekit.user.listUsers(\n { pageSize: 100 });" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "# pass empty org to fetch all users in environment\nresp,_ = scalekit_client.users.list_users(organization_id=\"\", page_size=100)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "all, err := scalekitClient.User().ListUsers(ctx, &scalekit.ListUsersOptions{PageSize: 100})" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListUsersRequest lur = ListUsersRequest.\n newBuilder().setPageSize(100).build();\nListUsersResponse allUsers = users.listUsers(lur);" + } + ] + } + }, + "/api/v1/users/{id}": { + "get": { + "description": "Retrieves all details for a user by system-generated user ID or external ID. The response includes organization memberships and user metadata.", + "tags": [ + "Users" + ], + "summary": "Get user", + "operationId": "UserService_GetUser", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "System-generated user ID", + "name": "id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Your application's unique identifier for this organization, used to link Scalekit with your system.", + "name": "external_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "User details retrieved successfully. Returns full user object with system-generated fields and timestamps.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersGetUserResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const { user } = await scalekit.user.getUser(\"usr_123456\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "resp = scalekit_client.users.get_user(user_id=\"usr_123456\")\nuser = resp.user" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.User().GetUser(ctx, \"usr_123456\")\nif err != nil {\n // handle error\n}\nuser := resp.User" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "GetUserResponse resp = scalekitClient.users().getUser(\"usr_123456\");\nUser user = resp.getUser();" + } + ] + }, + "delete": { + "description": "Permanently removes a user from your environment and deletes all associated data. Use this endpoint when you need to completely remove a user account. This action deletes the user's profile, memberships, and all related data across all organizations. This operation cannot be undone, so use with caution.", + "tags": [ + "Users" + ], + "summary": "Delete user permanently", + "operationId": "UserService_DeleteUser", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "System-generated user ID. Must start with 'usr_' (19-25 characters)", + "name": "id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "External system identifier from connected directories. Must match existing records", + "name": "external_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "User successfully deleted. No content returned", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.user.deleteUser(\"usr_123\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "scalekit_client.users.delete_user(organization_id=\"org_123\", \n user_id=\"usr_123\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "if err := scalekitClient.User().DeleteUser(ctx, \n \"usr_123\"); err != nil {\n panic(err)\n}" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "users.deleteUser(\"usr_123\");" + } + ] + }, + "patch": { + "description": "Modifies user account information including profile details, metadata, and external ID. Use this endpoint to update a user's personal information, contact details, or custom metadata. You can update the user's profile, phone number, and metadata fields. Note that fields like user ID, email address, environment ID, and creation time cannot be modified.", + "tags": [ + "Users" + ], + "summary": "Update user information", + "operationId": "UserService_UpdateUser", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "System-generated user ID. Must start with 'usr_' and be 19-25 characters long.", + "name": "id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "description": "Your application's unique identifier for this organization, used to link Scalekit with your system.", + "name": "external_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "User updated successfully. Returns the modified user object with updated timestamps.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersUpdateUserResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "await scalekit.user.updateUser(\"usr_123\", {\n\tuserProfile: {\n\t\tfirstName: \"John\",\n\t\tlastName: \"Smith\",\n\t},\n\tmetadata: {\n\t\tdepartment: \"sales\",\n\t},\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "import os\nfrom scalekit import ScalekitClient\nfrom scalekit.v1.users.users_pb2 import UpdateUser\nfrom scalekit.v1.commons.commons_pb2 import UserProfile\nscalekit_client = ScalekitClient(\n env_url=os.getenv(\"SCALEKIT_ENV_URL\"),\n client_id=os.getenv(\"SCALEKIT_CLIENT_ID\"),\n client_secret=os.getenv(\"SCALEKIT_CLIENT_SECRET\"),\n)\nupdate_user = UpdateUser(\n user_profile=UserProfile(\n first_name=\"John\",\n last_name=\"Smith\"\n ),\n metadata={\"department\": \"sales\"}\n)\nscalekit_client.users.update_user(organization_id=\"org_123\", \n user=update_user)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "upd := &usersv1.UpdateUser{\n UserProfile: &usersv1.UpdateUserProfile{\n FirstName: \"John\",\n LastName: \"Smith\",\n },\n Metadata: map[string]string{\n \"department\": \"sales\",\n },\n}\nscalekitClient.User().UpdateUser(ctx, \"usr_123\", upd)" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "UpdateUser upd = UpdateUser.newBuilder()\n .setUserProfile(\n UpdateUserProfile.newBuilder()\n .setFirstName(\"John\")\n .setLastName(\"Smith\")\n .build())\n .putMetadata(\"department\", \"sales\")\n .build();\nUpdateUserRequest updReq = UpdateUserRequest.\n newBuilder().setUser(upd).build();\nusers.updateUser(\"usr_123\", updReq);" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "description": "User fields to update. Only specified fields will be modified. Required fields must be provided if being changed.", + "$ref": "#/components/schemas/v1usersUpdateUser", + "examples": [ + { + "firstName": "John", + "lastName": "Doe" + } + ] + } + } + }, + "required": true + } + } + }, + "/api/v1/users/{user_id}/sessions": { + "get": { + "description": "Retrieves a paginated list of all sessions associated with a specific user across all devices and browsers. Use this endpoint to audit user activity, display all active sessions in account management interfaces, or verify user authentication status across devices. Supports filtering by session status (active, expired, revoked, logout) and time range (creation date). Returns session details for each session including device information, IP address, geolocation, and current status. The response includes pagination metadata (page tokens and total count) to handle large session lists efficiently.", + "tags": [ + "Sessions" + ], + "summary": "List user sessions", + "operationId": "SessionService_GetUserSessions", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the user whose sessions to retrieve. Must start with 'usr_' prefix.", + "name": "user_id", + "in": "path", + "required": true + }, + { + "schema": { + "type": "integer", + "format": "int64" + }, + "description": "Maximum number of sessions to return in a single page. Optional parameter. If not specified, defaults to a server-defined limit. Use smaller values for faster responses, larger values for fewer requests.", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Pagination token from the previous response for retrieving the next page of results. Leave empty for the first page. Use the next_page_token from a previous response to fetch subsequent pages.", + "name": "page_token", + "in": "query" + }, + { + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "style": "form", + "explode": true, + "description": "Filter sessions by one or more status values. Possible values: 'active', 'expired', 'revoked', 'logout'. Leave empty to include all statuses. Multiple values use OR logic (e.g., status=['active', 'expired'] returns sessions that are either active OR expired).", + "name": "filter.status", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "date-time" + }, + "description": "Filter to include only sessions created on or after this timestamp. Optional. Uses RFC 3339 format. Useful for querying sessions within a specific time window.", + "name": "filter.start_time", + "in": "query" + }, + { + "schema": { + "type": "string", + "format": "date-time" + }, + "description": "Filter to include only sessions created on or before this timestamp. Optional. Uses RFC 3339 format. Must be after start_time if both are specified.", + "name": "filter.end_time", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved user sessions. Returns a list of sessions with pagination information", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/sessionsUserSessionDetails" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "// Basic usage\nconst res = await scalekit.session.getUserSessions(\"user_123\");\n\n// With pagination and filtering\nconst res = await scalekit.session.getUserSessions(\"user_123\", {\n pageSize: 10,\n pageToken: \"next_page_token\",\n filter: {\n status: [\"ACTIVE\"],\n startTime: new Date(\"2024-01-01\"),\n endTime: new Date(\"2024-12-31\")\n }\n});" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "# Basic usage\nres = scalekit_client.sessions.get_user_sessions(user_id=\"user_123\")\n\n# With pagination and filtering\nfrom google.protobuf.timestamp_pb2 import Timestamp\nfrom datetime import datetime\n\nstart_time = Timestamp()\nstart_time.FromDatetime(datetime(2024, 1, 1))\nend_time = Timestamp()\nend_time.FromDatetime(datetime(2024, 12, 31))\n\nfilter_obj = scalekit_client.sessions.create_session_filter(\n status=[\"ACTIVE\"], start_time=start_time, end_time=end_time\n)\nres = scalekit_client.sessions.get_user_sessions(\n user_id=\"user_123\", page_size=10, page_token=\"next_page_token\", filter=filter_obj\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "// Basic usage\nresp, err := scalekitClient.Session().GetUserSessions(ctx, \"user_123\", 0, \"\", nil)\nif err != nil { /* handle err */ }\n\n// With pagination and filtering\n// import \"time\", sessionsv1 \"...\", \"google.golang.org/protobuf/types/known/timestamppb\"\nstartTime, _ := time.Parse(time.RFC3339, \"2024-01-01T00:00:00Z\")\nendTime, _ := time.Parse(time.RFC3339, \"2024-12-31T23:59:59Z\")\nfilter := &sessionsv1.UserSessionFilter{\n Status: []string{\"ACTIVE\"},\n StartTime: timestamppb.New(startTime),\n EndTime: timestamppb.New(endTime),\n}\nresp, err := scalekitClient.Session().GetUserSessions(ctx, \"user_123\", 10, \"next_page_token\", filter)\nif err != nil { /* handle err */ }" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "// Basic usage\nUserSessionDetails res = scalekitClient.sessions().getUserSessions(\"user_123\", null, null, null);\n\n// With pagination and filtering\n// import UserSessionFilter, Timestamp, Instant\nUserSessionFilter filter = UserSessionFilter.newBuilder()\n .addStatus(\"ACTIVE\")\n .setStartTime(Timestamp.newBuilder().setSeconds(Instant.parse(\"2024-01-01T00:00:00Z\").getEpochSecond()).build())\n .setEndTime(Timestamp.newBuilder().setSeconds(Instant.parse(\"2024-12-31T23:59:59Z\").getEpochSecond()).build())\n .build();\nUserSessionDetails res = scalekitClient.sessions().getUserSessions(\"user_123\", 10, \"next_page_token\", filter);" + } + ] + } + }, + "/api/v1/users/{user_id}/sessions/revoke": { + "post": { + "description": "Immediately invalidates all active sessions for a specific user across all devices and browsers, setting their status to 'revoked'. Use this endpoint to implement global logout functionality, force re-authentication after security incidents, or terminate all sessions following a password reset or credential compromise. Only active sessions are revoked; already expired, logout, or previously revoked sessions remain unchanged. The revocation is atomic and instantaneous. Returns a list of all revoked sessions with their details and a total count of sessions revoked.", + "tags": [ + "Sessions" + ], + "summary": "Revoke all user sessions", + "operationId": "SessionService_RevokeAllUserSessions", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "Unique identifier for the user whose all sessions will be revoked. Must start with 'usr_' prefix.", + "name": "user_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully revoked all user sessions. Returns the list of revoked sessions and total count", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/sessionsRevokeAllUserSessionsResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.session.revokeAllUserSessions(\"user_123\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.sessions.revoke_all_user_sessions(user_id=\"user_123\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.Session().RevokeAllUserSessions(ctx, \"user_123\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "RevokeAllUserSessionsResponse res = scalekitClient.sessions().revokeAllUserSessions(\"user_123\");" + } + ] + } + }, + "/api/v1/users:search": { + "get": { + "description": "Searches for users across the entire environment by email address, user ID, or external ID. The query must be at least 3 characters and is case-insensitive. Returns a paginated list of matching users with up to 30 results per page. Use the next_page_token from the response to retrieve subsequent pages.", + "tags": [ + "Users" + ], + "summary": "Search users", + "operationId": "UserService_SearchUsers", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 3, + "maxLength": 100 + }, + "description": "Search term to match against user email, IDs, or external IDs. Must be at least 3 characters. Case insensitive.", + "name": "query", + "in": "query", + "required": true + }, + { + "schema": { + "type": "integer", + "format": "int64", + "minimum": 1, + "maximum": 30 + }, + "description": "Maximum number of users to return per page. Value must be between 1 and 30.", + "name": "page_size", + "in": "query" + }, + { + "schema": { + "type": "string" + }, + "description": "Token from a previous response for pagination. Provide this to retrieve the next page of results.", + "name": "page_token", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Matching users returned; includes pagination cursors for navigating large result sets.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersSearchUsersResponse" + } + } + } + }, + "400": { + "description": "Bad Request - query must be at least 3 characters and no more than 100 characters.", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, + "/api/v1/webauthn/credentials": { + "get": { + "description": "Retrieves all registered passkeys for the current user, including device information, creation timestamps, and display names. Use this to show users their registered authenticators.", + "tags": [ + "Passkeys" + ], + "summary": "List user's passkeys", + "operationId": "WebAuthnService_ListCredentials", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "User ID to list credentials for (optional, current user if not provided)", + "name": "user_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "List of passkeys with metadata", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/webauthnListCredentialsResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.webauthn.listCredentials(\"user_123\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.webauthn.list_credentials(user_id=\"user_123\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.WebAuthn().ListCredentials(ctx, \"user_123\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "ListCredentialsResponse res = scalekitClient.webauthn().listCredentials(\"user_123\");" + } + ] + } + }, + "/api/v1/webauthn/credentials/{credential_id}": { + "delete": { + "description": "Deletes a specific passkey credential for the current user. After removal, the authenticator can no longer be used for authentication.", + "tags": [ + "Passkeys" + ], + "summary": "Remove a passkey", + "operationId": "WebAuthnService_DeleteCredential", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "The credential ID to delete", + "name": "credential_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Passkey successfully deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/webauthnDeleteCredentialResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.webauthn.deleteCredential(\"wac_123\");" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.webauthn.delete_credential(credential_id=\"wac_123\")" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.WebAuthn().DeleteCredential(ctx, \"wac_123\")\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "DeleteCredentialResponse res = scalekitClient.webauthn().deleteCredential(\"wac_123\");" + } + ] + }, + "patch": { + "description": "Updates the display name of a passkey credential to help users identify their authenticators. Only the display name can be modified.", + "tags": [ + "Passkeys" + ], + "summary": "Rename a passkey", + "operationId": "WebAuthnService_UpdateCredential", + "parameters": [ + { + "schema": { + "type": "string" + }, + "description": "The credential ID to update", + "name": "credential_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Passkey successfully updated with new name", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/webauthnUpdateCredentialResponse" + } + } + } + } + }, + "x-codeSamples": [ + { + "label": "Node.js SDK", + "lang": "javascript", + "source": "const res = await scalekit.webauthn.updateCredential(\n \"wac_123\",\n \"Work Laptop Passkey\"\n);" + }, + { + "label": "Python SDK", + "lang": "python", + "source": "res = scalekit_client.webauthn.update_credential(\n credential_id=\"wac_123\",\n display_name=\"Work Laptop Passkey\"\n)" + }, + { + "label": "Go SDK", + "lang": "go", + "source": "resp, err := scalekitClient.WebAuthn().UpdateCredential(\n ctx,\n \"wac_123\",\n \"Work Laptop Passkey\",\n)\nif err != nil { /* handle err */ }\n_ = resp" + }, + { + "label": "Java SDK", + "lang": "java", + "source": "UpdateCredentialResponse res = scalekitClient.webauthn()\n .updateCredential(\"wac_123\", \"Work Laptop Passkey\");" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WebAuthnServiceUpdateCredentialBody" + } + } + }, + "required": true + } + } + } + }, + "webhooks": { + "organization.created": { + "post": { + "summary": "Organization Created", + "description": "Triggered when a new organization is created in Scalekit", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_1234567890", + "type": "organization.created", + "object": "Organization", + "occurred_at": "2024-01-15T10:30:00.123456789Z", + "environment_id": "env_1234567890", + "organization_id": "org_1234567890", + "data": { + "create_time": "2025-12-09T09:25:02.02Z", + "display_name": "AcmeCorp", + "external_id": "org_external_123", + "id": "org_1234567890", + "metadata": null, + "region_code": "US", + "update_time": "2025-12-09T09:25:02.025330364Z", + "settings": { + "features": [ + { + "enabled": true, + "name": "sso" + }, + { + "enabled": false, + "name": "dir_sync" + } + ] + } + }, + "display_name": "Organization Created" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.updated": { + "post": { + "summary": "Organization Updated", + "description": "Triggered when an organization is updated", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_2345678901", + "type": "organization.updated", + "object": "Organization", + "occurred_at": "2024-01-15T10:35:00.123456789Z", + "environment_id": "env_1234567890", + "organization_id": "org_1234567890", + "data": { + "create_time": "2025-12-09T09:25:02.02Z", + "display_name": "AcmeCorp", + "external_id": "org_external_123", + "id": "org_1234567890", + "metadata": null, + "region_code": "US", + "update_time": "2025-12-09T09:25:02.025330364Z", + "settings": { + "features": [ + { + "enabled": true, + "name": "sso" + }, + { + "enabled": false, + "name": "dir_sync" + } + ] + } + }, + "display_name": "Organization Updated" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.deleted": { + "post": { + "summary": "Organization Deleted", + "description": "Triggered when an organization is deleted", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_3456789012", + "type": "organization.deleted", + "object": "Organization", + "occurred_at": "2024-01-15T10:40:00.123456789Z", + "environment_id": "env_1234567890", + "organization_id": "org_1234567890", + "data": { + "create_time": "2025-12-09T09:25:02.02Z", + "deleted_at": "2025-12-09T10:25:45.337417Z", + "display_name": "AcmeCorp", + "external_id": "org_external_123", + "id": "org_1234567890", + "metadata": null, + "region_code": "US", + "update_time": "2025-12-09T09:25:02.025330364Z", + "settings": { + "features": [ + { + "enabled": true, + "name": "sso" + }, + { + "enabled": false, + "name": "dir_sync" + } + ] + } + }, + "display_name": "Organization Deleted" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "user.signup": { + "post": { + "summary": "User Signup", + "description": "Triggered when a user signs up to create a new organization", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_1234567890", + "type": "user.signup", + "object": "OrgMembership", + "occurred_at": "2024-01-15T10:30:00.123456789Z", + "environment_id": "env_1234567890", + "organization_id": "org_102690563312124938", + "data": { + "organization": { + "id": "org_102690563312124938", + "create_time": "2025-12-09T10:19:05.48Z", + "display_name": "", + "external_id": null, + "metadata": null, + "region_code": "US", + "update_time": "2025-12-09T12:04:41.386974738Z", + "settings": { + "features": [ + { + "enabled": true, + "name": "sso" + }, + { + "enabled": true, + "name": "dir_sync" + } + ] + } + }, + "user": { + "create_time": "2025-12-09T12:04:41.39Z", + "email": "amit.ash1996@gmail.com", + "external_id": "", + "id": "usr_102701193205121289", + "metadata": {}, + "update_time": "2025-12-09T12:04:41.391988278Z", + "user_profile": { + "custom_attributes": null, + "email_verified": true, + "external_identities": null, + "family_name": "doe", + "gender": "", + "given_name": "John", + "groups": null, + "id": "usp_102701193205186825", + "locale": "", + "metadata": {}, + "name": "John Doe", + "phone_number": "", + "phone_number_verified": false, + "picture": "https://lh3.googleusercontent.com/a/abcdef", + "preferred_username": "" + } + } + }, + "display_name": "User Signup" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "user.login": { + "post": { + "summary": "User Login", + "description": "Triggered when a user logs in and a session is created", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_102701193859432713", + "type": "user.login", + "object": "User", + "occurred_at": "2025-12-09T12:04:41.781873312Z", + "environment_id": "env_96736846679245078", + "organization_id": "org_102701193188409609", + "data": { + "user": { + "create_time": "2025-12-09T12:04:41.39Z", + "email": "john.doe@acmecorp.com", + "external_id": "ext_123456789", + "id": "usr_123456789", + "last_login_time": "2025-12-09T12:04:41.48Z", + "metadata": {}, + "update_time": "2025-12-09T12:04:41.391988Z", + "user_profile": { + "custom_attributes": null, + "email_verified": true, + "external_identities": [ + { + "connection_id": "conn_97896332307464201", + "connection_provider": "GOOGLE", + "connection_type": "OAUTH", + "connection_user_id": "105055379523565727691", + "created_time": "2025-12-09T12:04:41.47Z", + "is_social": true, + "last_login_time": "2025-12-09T12:04:41.469311Z", + "last_synced_time": "2025-12-09T12:04:41.469311Z" + } + ], + "family_name": "Doe", + "gender": "", + "given_name": "John", + "groups": null, + "id": "usp_102701193205186825", + "locale": "", + "metadata": {}, + "name": "John Doe", + "phone_number": "", + "phone_number_verified": false, + "picture": "https://lh3.googleusercontent.com/a/abcdef", + "preferred_username": "" + } + }, + "user_session": { + "absolute_expires_at": "2026-01-08T12:04:41.737394Z", + "authenticated_organizations": [ + "org_102701193188409609" + ], + "created_at": "2025-12-09T12:04:41.48Z", + "expired_at": null, + "idle_expires_at": "2025-12-16T12:04:41.737395Z", + "last_active_at": "2025-12-09T12:04:41.747206Z", + "logout_at": null, + "organization_id": "org_102701193188409609", + "session_id": "ses_102701193356116233", + "status": "ACTIVE", + "updated_at": "2025-12-09T12:04:41.748512Z", + "user_id": "usr_102701193205121289", + "device": { + "browser": "Chrome", + "browser_version": "142.0.0.0", + "device_type": "Desktop", + "ip": "152.59.144.211", + "location": { + "city": "Patna", + "latitude": "25.594095", + "longitude": "85.137564", + "region": "IN", + "region_subdivision": "INBR" + }, + "os": "macOS", + "os_version": "10.15.7", + "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" + } + } + }, + "display_name": "User Login" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "user.logout": { + "post": { + "summary": "User Logout", + "description": "Triggered when a user's session is terminated", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_102708230123160586", + "type": "user.logout", + "object": "User", + "occurred_at": "2025-12-09T13:14:35.722070822Z", + "environment_id": "env_96736846679245078", + "organization_id": "org_102701193188409609", + "data": { + "user": { + "create_time": "2025-12-09T12:04:41.39Z", + "email": "john.doe@acmecorp.com", + "external_id": "ext_123456789", + "id": "usr_123456789", + "last_login_time": "2025-12-09T12:04:41.48Z", + "metadata": {}, + "update_time": "2025-12-09T12:04:41.391988Z", + "user_profile": { + "custom_attributes": null, + "email_verified": true, + "external_identities": [ + { + "connection_id": "conn_97896332307464201", + "connection_provider": "GOOGLE", + "connection_type": "OAUTH", + "connection_user_id": "105055379523565727691", + "created_time": "2025-12-09T12:04:41.47Z", + "is_social": true, + "last_login_time": "2025-12-09T12:04:41.469311Z", + "last_synced_time": "2025-12-09T12:04:41.469311Z" + } + ], + "family_name": "Doe", + "gender": "", + "given_name": "John", + "groups": null, + "id": "usp_102701193205186825", + "locale": "", + "metadata": {}, + "name": "John Doe", + "phone_number": "", + "phone_number_verified": false, + "picture": "https://lh3.googleusercontent.com/a/abcdef", + "preferred_username": "" + } + }, + "user_session": { + "absolute_expires_at": "2026-01-08T12:04:41.737394Z", + "authenticated_organizations": [ + "org_102701193188409609" + ], + "created_at": "2025-12-09T12:04:41.48Z", + "expired_at": null, + "idle_expires_at": "2025-12-16T12:04:41.737395Z", + "last_active_at": "2025-12-09T12:04:41.747206Z", + "logout_at": null, + "organization_id": "org_102701193188409609", + "session_id": "ses_102701193356116233", + "status": "ACTIVE", + "updated_at": "2025-12-09T12:04:41.748512Z", + "user_id": "usr_102701193205121289", + "device": { + "browser": "Chrome", + "browser_version": "142.0.0.0", + "device_type": "Desktop", + "ip": "152.59.144.211", + "location": { + "city": "Patna", + "latitude": "25.594095", + "longitude": "85.137564", + "region": "IN", + "region_subdivision": "INBR" + }, + "os": "macOS", + "os_version": "10.15.7", + "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" + } + } + }, + "display_name": "User Logout" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "user.organization_invitation": { + "post": { + "summary": "User Organization Invitation", + "description": "Triggered when a user is invited to join an organization", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_4567890123", + "type": "user.organization_invitation", + "object": "OrgMembership", + "occurred_at": "2024-01-15T11:00:00.123456789Z", + "environment_id": "env_1234567890", + "organization_id": "org_102690563312124938", + "data": { + "organization": { + "id": "org_102690563312124938", + "create_time": "2025-12-09T10:19:05.48Z", + "display_name": "Acme Corp", + "external_id": "org_external_123", + "metadata": null, + "region_code": "US", + "update_time": "2025-12-09T12:04:41.386974738Z", + "settings": { + "features": [ + { + "enabled": true, + "name": "sso" + }, + { + "enabled": true, + "name": "dir_sync" + } + ] + } + }, + "user": { + "create_time": "2025-12-09T12:04:41.39Z", + "email": "john.doe@acmecorp.com", + "external_id": "ext_123456789", + "id": "usr_123456789", + "metadata": {}, + "update_time": "2025-12-09T12:04:41.391988Z", + "user_profile": { + "custom_attributes": null, + "email_verified": true, + "external_identities": [ + { + "connection_id": "conn_97896332307464201", + "connection_provider": "GOOGLE", + "connection_type": "OAUTH", + "connection_user_id": "105055379523565727691", + "created_time": "2025-12-09T12:04:41.47Z", + "is_social": true, + "last_login_time": "2025-12-09T12:04:41.469311Z", + "last_synced_time": "2025-12-09T12:04:41.469311Z" + } + ], + "family_name": "Doe", + "gender": "", + "given_name": "John", + "groups": null, + "id": "usp_102701193205186825", + "locale": "", + "metadata": {}, + "name": "John Doe", + "phone_number": "", + "phone_number_verified": false, + "picture": "https://lh3.googleusercontent.com/a/abcdef", + "preferred_username": "" + } + } + }, + "display_name": "User Organization Invitation" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "user.organization_membership_created": { + "post": { + "summary": "User Organization Membership Created", + "description": "Triggered when a user joins an organization", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_5678901234", + "type": "user.organization_membership_created", + "object": "OrgMembership", + "occurred_at": "2024-01-15T11:05:00.123456789Z", + "environment_id": "env_1234567890", + "organization_id": "org_102690563312124938", + "data": { + "organization": { + "id": "org_102690563312124938", + "create_time": "2025-12-09T10:19:05.48Z", + "display_name": "Acme Corp", + "external_id": "org_external_123", + "metadata": null, + "region_code": "US", + "update_time": "2025-12-09T12:04:41.386974738Z", + "settings": { + "features": [ + { + "enabled": true, + "name": "sso" + }, + { + "enabled": true, + "name": "dir_sync" + } + ] + } + }, + "user": { + "create_time": "2025-12-09T12:04:41.39Z", + "email": "john.doe@acmecorp.com", + "external_id": "ext_123456789", + "id": "usr_123456789", + "metadata": {}, + "update_time": "2025-12-09T12:04:41.391988Z", + "user_profile": { + "custom_attributes": null, + "email_verified": true, + "external_identities": [ + { + "connection_id": "conn_97896332307464201", + "connection_provider": "GOOGLE", + "connection_type": "OAUTH", + "connection_user_id": "105055379523565727691", + "created_time": "2025-12-09T12:04:41.47Z", + "is_social": true, + "last_login_time": "2025-12-09T12:04:41.469311Z", + "last_synced_time": "2025-12-09T12:04:41.469311Z" + } + ], + "family_name": "Doe", + "gender": "", + "given_name": "John", + "groups": null, + "id": "usp_102701193205186825", + "locale": "", + "metadata": {}, + "name": "John Doe", + "phone_number": "", + "phone_number_verified": false, + "picture": "https://lh3.googleusercontent.com/a/abcdef", + "preferred_username": "" + } + } + }, + "display_name": "User Organization Membership Created" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "user.organization_membership_deleted": { + "post": { + "summary": "User Organization Membership Deleted", + "description": "Triggered when a user's membership in an organization is removed or deleted", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_9012345678", + "type": "user.organization_membership_deleted", + "object": "OrgMembership", + "occurred_at": "2024-01-15T11:10:00.123456789Z", + "environment_id": "env_1234567890", + "organization_id": "org_102690563312124938", + "data": { + "organization": { + "id": "org_102690563312124938", + "create_time": "2025-12-09T10:19:05.48Z", + "display_name": "Acme Corp", + "external_id": "org_external_123", + "metadata": null, + "region_code": "US", + "update_time": "2025-12-09T12:04:41.386974738Z", + "settings": { + "features": [ + { + "enabled": true, + "name": "sso" + }, + { + "enabled": true, + "name": "dir_sync" + } + ] + } + }, + "user": { + "create_time": "2025-12-09T12:04:41.39Z", + "email": "john.doe@acmecorp.com", + "external_id": "ext_123456789", + "id": "usr_123456789", + "metadata": {}, + "update_time": "2025-12-09T12:04:41.391988Z", + "user_profile": { + "custom_attributes": null, + "email_verified": true, + "external_identities": [ + { + "connection_id": "conn_97896332307464201", + "connection_provider": "GOOGLE", + "connection_type": "OAUTH", + "connection_user_id": "105055379523565727691", + "created_time": "2025-12-09T12:04:41.47Z", + "is_social": true, + "last_login_time": "2025-12-09T12:04:41.469311Z", + "last_synced_time": "2025-12-09T12:04:41.469311Z", + "raw_attributes": "{}", + "updated_time": "2025-12-09T12:04:41.473087Z" + } + ], + "family_name": "Doe", + "gender": "", + "given_name": "John", + "locale": "", + "metadata": {}, + "name": "John Doe", + "phone_number": "", + "phone_number_verified": false, + "picture": "https://lh3.googleusercontent.com/a/abcdef", + "preferred_username": "" + } + } + }, + "display_name": "User Organization Membership Deleted" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "user.organization_membership_updated": { + "post": { + "summary": "User Organization Membership Updated", + "description": "Triggered when a user's organization membership is updated, e.g., change of user's role in an organization", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_6789012345", + "type": "user.organization_membership_updated", + "object": "OrgMembership", + "occurred_at": "2024-01-15T11:10:00.123456789Z", + "environment_id": "env_1234567890", + "organization_id": "org_102690563312124938", + "data": { + "organization": { + "id": "org_102690563312124938", + "create_time": "2025-12-09T10:19:05.48Z", + "display_name": "Acme Corp", + "external_id": "org_external_123", + "metadata": null, + "region_code": "US", + "update_time": "2025-12-09T12:04:41.386974738Z", + "settings": { + "features": [ + { + "enabled": true, + "name": "sso" + }, + { + "enabled": true, + "name": "dir_sync" + } + ] + } + }, + "user": { + "create_time": "2025-12-09T12:04:41.39Z", + "email": "john.doe@acmecorp.com", + "external_id": "ext_123456789", + "id": "usr_123456789", + "metadata": {}, + "update_time": "2025-12-09T12:04:41.391988Z", + "user_profile": { + "custom_attributes": null, + "email_verified": true, + "external_identities": [ + { + "connection_id": "conn_97896332307464201", + "connection_provider": "GOOGLE", + "connection_type": "OAUTH", + "connection_user_id": "105055379523565727691", + "created_time": "2025-12-09T12:04:41.47Z", + "is_social": true, + "last_login_time": "2025-12-09T12:04:41.469311Z", + "last_synced_time": "2025-12-09T12:04:41.469311Z", + "raw_attributes": "{}", + "updated_time": "2025-12-09T12:04:41.473087Z" + } + ], + "family_name": "Doe", + "gender": "", + "given_name": "John", + "locale": "", + "metadata": {}, + "name": "John Doe", + "phone_number": "", + "phone_number_verified": false, + "picture": "https://lh3.googleusercontent.com/a/abcdef", + "preferred_username": "" + } + } + }, + "display_name": "User Organization Membership Updated" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.directory_enabled": { + "post": { + "summary": "Directory Enabled", + "description": "Triggered when a directory sync is enabled", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_55136848686613000", + "type": "organization.directory_enabled", + "object": "Directory", + "occurred_at": "2025-01-15T08:55:22.802860294Z", + "environment_id": "env_27758032200925221", + "organization_id": "org_55135410258444802", + "data": { + "directory_type": "SCIM", + "enabled": true, + "id": "dir_55135622825771522", + "organization_id": "org_55135410258444802", + "provider": "OKTA", + "updated_at": "2025-01-15T08:55:22.792993454Z" + }, + "display_name": "Directory Enabled" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.directory_disabled": { + "post": { + "summary": "Directory Disabled", + "description": "Triggered when a directory sync is disabled", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_53891640779079756", + "type": "organization.directory_disabled", + "object": "Directory", + "occurred_at": "2025-01-06T18:45:21.057814Z", + "environment_id": "env_53814739859406915", + "organization_id": "org_53879494091473415", + "data": { + "directory_type": "SCIM", + "enabled": false, + "id": "dir_53879621145330183", + "organization_id": "org_53879494091473415", + "provider": "OKTA", + "updated_at": "2025-01-06T18:45:21.04978184Z" + }, + "display_name": "Directory Disabled" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.directory.user_created": { + "post": { + "summary": "Directory User Created", + "description": "Triggered when a new directory user is created", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_53891546994442316", + "type": "organization.directory.user_created", + "object": "DirectoryUser", + "occurred_at": "2025-01-06T18:44:25.153954Z", + "environment_id": "env_53814739859406915", + "organization_id": "org_53879494091473415", + "data": { + "active": true, + "cost_center": "QAUZJUHSTYCN", + "custom_attributes": { + "mobile_phone_number": "1-579-4072" + }, + "department": "HNXJPGISMIFN", + "division": "MJFUEYJOKICN", + "dp_id": "", + "email": "flavio@runolfsdottir.co.duk", + "employee_id": "AWNEDTILGaIZN", + "family_name": "Jaquelin", + "given_name": "Dayton", + "groups": [ + { + "id": "dirgroup_12312312312312", + "name": "Group Name" + } + ], + "id": "diruser_53891546960887884", + "language": "se", + "locale": "LLWLEWESPLDC", + "name": "QDRGUZZDYMFU", + "nickname": "DTUODYKGFPPC", + "organization": "AUIITQVUQGVH", + "organization_id": "org_53879494091473415", + "phone_number": "1-579-4072", + "preferred_username": "kuntala1233a", + "profile": "YMIUQUHKGVAX", + "raw_attributes": {}, + "title": "FKQBHCWJXZSC", + "user_type": "RBQFJSQEFAEH", + "zoneinfo": "America/Araguaina", + "roles": [ + { + "role_name": "billing_admin" + } + ] + }, + "display_name": "Directory User Created" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.directory.user_updated": { + "post": { + "summary": "Directory User Updated", + "description": "Triggered when a directory user is updated", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_53891546994442317", + "type": "organization.directory.user_updated", + "object": "DirectoryUser", + "occurred_at": "2025-01-06T18:44:25.153954Z", + "environment_id": "env_53814739859406915", + "organization_id": "org_53879494091473415", + "data": { + "id": "diruser_12312312312312", + "organization_id": "org_53879494091473415", + "dp_id": "", + "preferred_username": "", + "email": "john.doe@example.com", + "active": true, + "name": "John Doe", + "roles": [ + { + "role_name": "billing_admin" + } + ], + "groups": [ + { + "id": "dirgroup_12312312312312", + "name": "Group Name" + } + ], + "given_name": "John", + "family_name": "Doe", + "nickname": "Jhonny boy", + "picture": "https://image.com/profile.jpg", + "phone_number": "1234567892", + "address": { + "postal_code": "64112", + "state": "Missouri", + "formatted": "123, Oxford Lane, Kansas City, Missouri, 64112" + }, + "custom_attributes": { + "attribute1": "value1", + "attribute2": "value2" + }, + "raw_attributes": {} + }, + "display_name": "Directory User Updated" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.directory.user_deleted": { + "post": { + "summary": "Directory User Deleted", + "description": "Triggered when a directory user is deleted", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_53891546994442318", + "type": "organization.directory.user_deleted", + "object": "DirectoryUser", + "occurred_at": "2025-01-06T18:44:25.153954Z", + "environment_id": "env_53814739859406915", + "organization_id": "org_53879494091473415", + "data": { + "id": "diruser_12312312312312", + "organization_id": "org_12312312312312", + "dp_id": "", + "email": "john.doe@example.com" + }, + "display_name": "Directory User Deleted" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.directory.group_created": { + "post": { + "summary": "Directory Group Created", + "description": "Triggered when a new directory group is created", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_38862741515010639", + "type": "organization.directory.group_created", + "object": "DirectoryGroup", + "occurred_at": "2024-09-25T02:26:39.036398577Z", + "environment_id": "env_32080745237316098", + "organization_id": "org_38609339635728478", + "data": { + "directory_id": "dir_38610496391217780", + "display_name": "Avengers", + "external_id": null, + "id": "dirgroup_38862741498233423", + "organization_id": "org_38609339635728478", + "raw_attributes": {} + }, + "display_name": "Directory Group Created" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.directory.group_updated": { + "post": { + "summary": "Directory Group Updated", + "description": "Triggered when a directory group is updated", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_38864948910162368", + "type": "organization.directory.group_updated", + "object": "DirectoryGroup", + "occurred_at": "2024-09-25T02:48:34.745030921Z", + "environment_id": "env_32080745237316098", + "organization_id": "org_38609339635728478", + "data": { + "directory_id": "dir_38610496391217780", + "display_name": "Avengers", + "external_id": "", + "id": "dirgroup_38862741498233423", + "organization_id": "org_38609339635728478", + "raw_attributes": {} + }, + "display_name": "Directory Group Updated" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.directory.group_deleted": { + "post": { + "summary": "Directory Group Deleted", + "description": "Triggered when a directory group is deleted", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_40650399597723966", + "type": "organization.directory.group_deleted", + "object": "DirectoryGroup", + "occurred_at": "2024-10-07T10:25:26.289331747Z", + "environment_id": "env_12205603854221623", + "organization_id": "org_39802449573184223", + "data": { + "directory_id": "dir_39802485862301855", + "display_name": "Admins", + "dp_id": "7c66a173-79c6-4270-ac78-8f35a8121e0a", + "id": "dirgroup_40072007005503806", + "organization_id": "org_39802449573184223", + "raw_attributes": {} + }, + "display_name": "Directory Group Deleted" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.sso_created": { + "post": { + "summary": "SSO Connection Created", + "description": "Triggered when a new SSO connection is created for an organization", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_94567862441607493", + "type": "organization.sso_created", + "object": "Connection", + "environment_id": "env_74418471961625391", + "occurred_at": "2025-10-14T09:27:18.488720586Z", + "organization_id": "org_83544995172188677", + "data": { + "id": "conn_94567862424830277", + "organization_id": "org_83544995172188677", + "connection_type": "OIDC", + "provider": "OKTA" + }, + "display_name": "SSO Connection Created" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.sso_enabled": { + "post": { + "summary": "SSO Connection Enabled", + "description": "Triggered when an SSO connection is enabled for an organization", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_94568078213382471", + "type": "organization.sso_enabled", + "object": "Connection", + "environment_id": "env_74418471961625391", + "occurred_at": "2025-10-14T09:29:27.098914861Z", + "organization_id": "org_83544995172188677", + "data": { + "id": "conn_94567862424830277", + "organization_id": "org_83544995172188677", + "connection_type": "OIDC", + "provider": "OKTA", + "enabled": true, + "status": "COMPLETED" + }, + "display_name": "SSO Connection Enabled" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.sso_disabled": { + "post": { + "summary": "SSO Connection Disabled", + "description": "Triggered when an SSO connection is disabled for an organization", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_94557976165089560", + "type": "organization.sso_disabled", + "object": "Connection", + "environment_id": "env_74418471961625391", + "occurred_at": "2025-10-14T07:49:05.809554456Z", + "organization_id": "org_83544995172188677", + "data": { + "id": "conn_83545002856153607", + "organization_id": "org_83544995172188677", + "connection_type": "OIDC", + "provider": "OKTA", + "enabled": false, + "status": "COMPLETED" + }, + "display_name": "SSO Connection Disabled" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "organization.sso_deleted": { + "post": { + "summary": "SSO Connection Deleted", + "description": "Triggered when an SSO connection is deleted for an organization", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_94557997639926040", + "type": "organization.sso_deleted", + "object": "Connection", + "environment_id": "env_74418471961625391", + "occurred_at": "2025-10-14T07:49:18.604546332Z", + "organization_id": "org_83544995172188677", + "data": { + "id": "conn_83545002856153607", + "organization_id": "org_83544995172188677", + "connection_type": "OIDC", + "provider": "OKTA" + }, + "display_name": "SSO Connection Deleted" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "role.created": { + "post": { + "summary": "Role Created", + "description": "Triggered when a new role is created", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_1234567890", + "type": "role.created", + "object": "Role", + "occurred_at": "2024-01-15T10:30:00.123456789Z", + "environment_id": "env_1234567890", + "data": { + "description": "Viewer role with read-only access", + "display_name": "Viewer", + "extends": "member", + "id": "role_1234567890", + "name": "viewer" + }, + "display_name": "Role Created" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "role.updated": { + "post": { + "summary": "Role Updated", + "description": "Triggered when a role is updated", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_2345678901", + "type": "role.updated", + "object": "Role", + "occurred_at": "2024-01-15T10:35:00.123456789Z", + "environment_id": "env_1234567890", + "data": { + "description": "Updated viewer role with limited permissions", + "display_name": "Viewer", + "extends": "member", + "id": "role_1234567890", + "name": "viewer" + }, + "display_name": "Role Updated" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "role.deleted": { + "post": { + "summary": "Role Deleted", + "description": "Triggered when a role is deleted", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_3456789012", + "type": "role.deleted", + "object": "Role", + "occurred_at": "2024-01-15T10:40:00.123456789Z", + "environment_id": "env_1234567890", + "data": { + "description": "Updated viewer role with limited permissions", + "display_name": "Viewer", + "extends": "member", + "id": "role_1234567890", + "name": "viewer" + }, + "display_name": "Role Deleted" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "permission.created": { + "post": { + "summary": "Permission Created", + "description": "Triggered when a new permission is created", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_1234567890", + "type": "permission.created", + "object": "Permission", + "occurred_at": "2024-01-15T10:30:00.123456789Z", + "environment_id": "env_1234567890", + "data": { + "description": "Permission to manage data", + "id": "perm_1234567890", + "name": "data:manage" + }, + "display_name": "Permission Created" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "permission.updated": { + "post": { + "summary": "Permission Updated", + "description": "Triggered when a permission is updated", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_2345678901", + "type": "permission.updated", + "object": "Permission", + "occurred_at": "2024-01-15T10:35:00.123456789Z", + "environment_id": "env_1234567890", + "data": { + "description": "Updated permission to manage all data", + "id": "perm_1234567890", + "name": "data:manage" + }, + "display_name": "Permission Updated" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + }, + "permission.deleted": { + "post": { + "summary": "Permission Deleted", + "description": "Triggered when a permission is deleted", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScalekitEvent" + }, + "example": { + "spec_version": "1", + "id": "evt_3456789012", + "type": "permission.deleted", + "object": "Permission", + "occurred_at": "2024-01-15T10:40:00.123456789Z", + "environment_id": "env_1234567890", + "data": { + "description": "Updated permission to manage all data", + "id": "perm_1234567890", + "name": "data:manage" + }, + "display_name": "Permission Deleted" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook received successfully" + } + } + } + } + }, + "components": { + "securitySchemes": { + "oauth2": { + "type": "oauth2", + "flows": { + "clientCredentials": { + "tokenUrl": "https://$SCALEKIT_ENVIRONMENT_URL/oauth/token", + "scopes": { + "": "No scope required for client credentials flow" + } + } + } + } + }, + "schemas": { + "connectionsConnectionProvider": { + "type": "string", + "enum": [ + "OKTA", + "GOOGLE", + "MICROSOFT_AD", + "AUTH0", + "ONELOGIN", + "PING_IDENTITY", + "JUMPCLOUD", + "CUSTOM", + "GITHUB", + "GITLAB", + "LINKEDIN", + "SALESFORCE", + "MICROSOFT", + "IDP_SIMULATOR", + "SCALEKIT", + "ADFS" + ] + }, + "connectionsConnectionStatus": { + "type": "string", + "enum": [ + "DRAFT", + "IN_PROGRESS", + "COMPLETED" + ] + }, + "connectionsConnectionType": { + "type": "string", + "enum": [ + "OIDC", + "SAML", + "PASSWORD", + "OAUTH", + "PASSWORDLESS", + "BASIC", + "BEARER", + "API_KEY", + "WEBAUTHN" + ] + }, + "connectionsListConnection": { + "type": "object", + "properties": { + "domains": { + "description": "List of domains configured with this connection", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "yourapp.com", + "yourworkspace.com" + ] + ] + }, + "enabled": { + "description": "Whether the connection is currently active for organization users", + "type": "boolean", + "examples": [ + false + ] + }, + "id": { + "description": "Unique identifier of the connection", + "type": "string", + "examples": [ + "conn_2123312131125533" + ] + }, + "key_id": { + "description": "Alternative identifier for this connection, typically used in frontend applications or URLs", + "type": "string", + "examples": [ + "conn_2123312131125533" + ] + }, + "organization_id": { + "description": "Unique identifier of the organization that owns this connection", + "type": "string", + "examples": [ + "org_2123312131125533" + ] + }, + "organization_name": { + "description": "Name of the organization of the connection", + "type": "string", + "examples": [ + "Your Organization" + ] + }, + "provider": { + "description": "Identity provider type (e.g., OKTA, Google, Azure AD)", + "$ref": "#/components/schemas/connectionsConnectionProvider", + "examples": [ + "CUSTOM" + ] + }, + "provider_key": { + "description": "Key ID of the identity provider service that handles authentication", + "type": "string", + "examples": [ + "google" + ] + }, + "status": { + "description": "Current configuration status of the connection", + "$ref": "#/components/schemas/connectionsConnectionStatus", + "readOnly": true, + "examples": [ + "IN_PROGRESS" + ] + }, + "type": { + "description": "Authentication protocol used by the connection", + "$ref": "#/components/schemas/connectionsConnectionType", + "examples": [ + "OIDC" + ] + } + } + }, + "connectionsListConnectionsResponse": { + "type": "object", + "properties": { + "connections": { + "description": "List of connections matching the request criteria", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/connectionsListConnection" + } + } + } + }, + "UserServiceResendInviteBody": { + "type": "object" + }, + "usersInvite": { + "type": "object", + "properties": { + "created_at": { + "description": "Timestamp when the invite was originally created.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-07-10T08:00:00Z" + ] + }, + "expires_at": { + "description": "The time at which the invite expires.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-12-31T23:59:59Z" + ] + }, + "inviter_email": { + "description": "Identifier of the user or system that initiated the invite.", + "type": "string", + "examples": [ + "admin@example.com" + ] + }, + "organization_id": { + "description": "The organization to which the invite belongs.", + "type": "string", + "examples": [ + "org_987654321" + ] + }, + "resent_at": { + "description": "Timestamp when the invite was last resent, if applicable.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-07-15T09:30:00Z" + ] + }, + "resent_count": { + "description": "Number of times the invite has been resent.", + "type": "integer", + "format": "int32", + "examples": [ + 2 + ] + }, + "status": { + "description": "Current status of the invite (e.g., pending, accepted, expired, revoked).", + "type": "string", + "examples": [ + "pending_invite" + ] + }, + "user_id": { + "description": "User ID to whom the invite is sent. May be empty if the user has not signed up yet.", + "type": "string", + "examples": [ + "usr_123456" + ] + } + } + }, + "usersResendInviteResponse": { + "type": "object", + "properties": { + "invite": { + "description": "Updated invitation object containing the resent invitation details, including new expiration time and incremented resend counter.", + "$ref": "#/components/schemas/usersInvite", + "examples": [ + { + "expires_at": "2025-12-31T23:59:59Z", + "organization_id": "org_123", + "resent_count": 2, + "status": "pending_invite", + "user_id": "usr_456" + } + ] + } + } + }, + "errdetailsDebugInfo": { + "description": "Describes additional debugging info.", + "type": "object", + "properties": { + "detail": { + "description": "Additional debugging information provided by the server.", + "type": "string" + }, + "stack_entries": { + "description": "The stack trace entries indicating where the error occurred.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "HelpInfoLink": { + "description": "A documentation or reference link.", + "type": "object", + "properties": { + "description": { + "description": "Human-readable label for the link (e.g. \"User verification flow\").", + "type": "string" + }, + "url": { + "description": "Absolute URL to the documentation page (e.g. \"https://docs.scalekit.com/...\").", + "type": "string" + } + } + }, + "errdetailsHelpInfo": { + "description": "HelpInfo provides documentation links attached to an error response.\nWhen present in ErrorInfo, clients should surface these links to help\ndevelopers resolve the error. For example, a missing required field error\nmay include a link to the relevant guide.", + "type": "object", + "properties": { + "links": { + "description": "One or more links relevant to resolving the error.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/HelpInfoLink" + } + } + } + }, + "errdetailsLocalizedMessageInfo": { + "type": "object", + "properties": { + "locale": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "errdetailsRequestInfo": { + "description": "Contains metadata about the request that clients can attach when filing a bug\nor providing other forms of feedback.", + "type": "object", + "properties": { + "request_id": { + "description": "An opaque string that should only be interpreted by the service generating\nit. For example, it can be used to identify requests in the service's logs.", + "type": "string" + }, + "serving_data": { + "description": "Any data that was used to serve this request. For example, an encrypted\nstack trace that can be sent back to the service provider for debugging.", + "type": "string" + } + } + }, + "errdetailsResourceInfo": { + "description": "Describes the resource that is being accessed.", + "type": "object", + "properties": { + "description": { + "description": "Describes what error is encountered when accessing this resource.\nFor example, updating a cloud project may require the `writer` permission\non the developer console project.", + "type": "string" + }, + "owner": { + "type": "string" + }, + "required_permissions": { + "description": "The required permissions needed to access the resource.", + "type": "array", + "items": { + "type": "string" + } + }, + "resource_name": { + "type": "string" + }, + "user": { + "type": "string" + } + } + }, + "errdetailsToolErrorInfo": { + "type": "object", + "properties": { + "execution_id": { + "type": "string" + }, + "tool_error_code": { + "type": "string" + }, + "tool_error_message": { + "type": "string" + } + } + }, + "ValidationErrorInfoFieldViolation": { + "description": "A message type used to describe a single bad request field.", + "type": "object", + "properties": { + "constraint": { + "type": "string" + }, + "description": { + "description": "A description of why the request element is bad.", + "type": "string" + }, + "field": { + "type": "string" + } + } + }, + "errdetailsValidationErrorInfo": { + "description": "Describes violations in a client request. This error type focuses on the\nsyntactic aspects of the request.", + "type": "object", + "properties": { + "field_violations": { + "description": "Describes all violations in a client request.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/ValidationErrorInfoFieldViolation" + } + } + } + }, + "errdetailsErrorInfo": { + "type": "object", + "properties": { + "debug_info": { + "$ref": "#/components/schemas/errdetailsDebugInfo" + }, + "error_code": { + "type": "string" + }, + "help_info": { + "$ref": "#/components/schemas/errdetailsHelpInfo" + }, + "localized_message_info": { + "$ref": "#/components/schemas/errdetailsLocalizedMessageInfo" + }, + "request_info": { + "$ref": "#/components/schemas/errdetailsRequestInfo" + }, + "resource_info": { + "$ref": "#/components/schemas/errdetailsResourceInfo" + }, + "tool_error_info": { + "$ref": "#/components/schemas/errdetailsToolErrorInfo" + }, + "validation_error_info": { + "$ref": "#/components/schemas/errdetailsValidationErrorInfo" + } + } + }, + "commonsRole": { + "type": "object", + "properties": { + "display_name": { + "description": "Human-readable name for the role", + "type": "string", + "examples": [ + "Dev Team" + ] + }, + "id": { + "description": "Role ID", + "type": "string", + "readOnly": true, + "examples": [ + "role_79643236410327240" + ] + }, + "name": { + "description": "Attribute name/identifier for the role used in system operations and API calls. This should be a machine-readable identifier that follows naming conventions.", + "type": "string", + "examples": [ + "team_dev" + ] + } + } + }, + "v1usersCreateMembership": { + "type": "object", + "properties": { + "inviter_email": { + "description": "Email address of the user who invited this member. Must be a valid email address.", + "type": "string", + "examples": [ + "john.doe@example.com" + ] + }, + "metadata": { + "description": "Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars).", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "department": "engineering", + "location": "nyc-office" + } + ] + }, + "roles": { + "description": "Role to assign to the user within the organization", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/commonsRole" + }, + "examples": [ + [ + { + "name": "admin" + } + ] + ] + } + } + }, + "commonsMembershipStatus": { + "type": "string", + "enum": [ + "ACTIVE", + "INACTIVE", + "PENDING_INVITE", + "INVITE_EXPIRED" + ] + }, + "commonsOrganizationMembership": { + "type": "object", + "properties": { + "accepted_at": { + "description": "Timestamp when the user accepted the invitation.", + "type": "string", + "format": "date-time" + }, + "created_at": { + "description": "Timestamp when the invitation was created.", + "type": "string", + "format": "date-time" + }, + "display_name": { + "description": "Organization display name. This field stores a user-friendly name for the organization that may be different from the formal name, often used for UI display purposes.", + "type": "string", + "examples": [ + "Acme Corporation" + ] + }, + "expires_at": { + "description": "Timestamp when the invitation expired.", + "type": "string", + "format": "date-time" + }, + "inviter_email": { + "description": "ID of the user who invited this user.", + "type": "string" + }, + "join_time": { + "description": "Timestamp when the membership was created. Automatically set by the server.", + "type": "string", + "format": "date-time" + }, + "membership_status": { + "$ref": "#/components/schemas/commonsMembershipStatus" + }, + "metadata": { + "description": "Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars).", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "department": "engineering", + "location": "nyc-office" + } + ] + }, + "name": { + "description": "Organization name. This field stores the formal organization name used for identification and display purposes.", + "type": "string", + "examples": [ + "AcmeCorp" + ] + }, + "organization_id": { + "description": "Unique identifier for the organization. Immutable and read-only.", + "type": "string", + "examples": [ + "org_1234abcd5678efgh" + ] + }, + "permissions": { + "description": "Effective permissions granted to the user within the organization (including inherited permissions from assigned roles). Lists the specific actions and access rights the user can perform.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "read_projects", + "write_tasks", + "manage_users" + ] + ] + }, + "provisioning_method": { + "description": "How the user was provisioned. \nPossible values: \n- `jit_using_sso` (Just-in-time provisioning during SSO login)\n- `allowed_email_domain` (User joined via allowed email domain matching)\n- `org_creator` (User created the organization)\n- `direct_provision` (User was directly provisioned via API or SCIM)\n- `invitation` (User was invited and accepted an invitation)", + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/commonsRole" + } + } + } + }, + "commonsIdentityProviderType": { + "type": "string", + "enum": [ + "OKTA", + "GOOGLE", + "MICROSOFT_AD", + "AUTH0", + "ONELOGIN", + "PING_IDENTITY", + "JUMPCLOUD", + "CUSTOM", + "GITHUB", + "GITLAB", + "LINKEDIN", + "SALESFORCE", + "MICROSOFT", + "IDP_SIMULATOR", + "SCALEKIT", + "ADFS" + ] + }, + "commonsExternalIdentity": { + "type": "object", + "properties": { + "connection_id": { + "description": "Unique identifier for the external identity connection. Immutable and read-only.", + "type": "string", + "readOnly": true, + "examples": [ + "conn_1234abcd5678efgh" + ] + }, + "connection_provider": { + "description": "Type of the identity provider.", + "$ref": "#/components/schemas/commonsIdentityProviderType", + "readOnly": true, + "examples": [ + "GOOGLE" + ] + }, + "connection_type": { + "description": "Name of the external identity connection.", + "type": "string", + "readOnly": true, + "examples": [ + "OAUTH" + ] + }, + "connection_user_id": { + "description": "Unique identifier for the user in the external identity provider system. Immutable and read-only.", + "type": "string", + "readOnly": true, + "examples": [ + "ext_user_12345" + ] + }, + "created_time": { + "description": "Timestamp when this external identity connection was first created. Immutable and read-only.", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "is_social": { + "description": "Indicates if the identity provider is a social provider (true) or enterprise/custom provider (false). Read-only.", + "type": "boolean", + "readOnly": true, + "examples": [ + true + ] + }, + "last_login_time": { + "description": "Timestamp of the user's last successful login via this external identity provider. Automatically updated by the system.", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "last_synced_time": { + "description": "Timestamp of the last data synchronization for this external identity from the provider. Automatically updated by the system.", + "type": "string", + "format": "date-time", + "readOnly": true + } + } + }, + "commonsUserProfile": { + "type": "object", + "properties": { + "custom_attributes": { + "description": "Custom attributes for extended user profile data and application-specific information. This field stores business-specific user data like department, job title, security clearances, project assignments, or any other organizational attributes your application requires. Unlike system metadata, these attributes are typically managed by administrators or applications and are visible to end users for personalization and business logic. Keys must be 3-25 characters, values must be 1-256 characters, with a maximum of 20 key-value pairs.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "department": "engineering", + "security_clearance": "level2" + } + ] + }, + "email_verified": { + "description": "Indicates if the user's email address has been verified. Automatically updated by the system.", + "type": "boolean", + "readOnly": true, + "examples": [ + true + ] + }, + "external_identities": { + "description": "List of external identity connections associated with the user profile.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/commonsExternalIdentity" + }, + "readOnly": true + }, + "family_name": { + "description": "The user's family name (last name or surname). This field stores the user's last name and is combined with the given name to create the full display name. The family name is used in formal communications, user listings, and organizational directories throughout the system. Maximum 255 characters allowed.", + "type": "string", + "examples": [ + "Doe" + ] + }, + "gender": { + "description": "The user's gender identity information. This field stores the user's gender identity for personalization, compliance reporting, or organizational analytics purposes. This field supports any string value to accommodate diverse gender identities and should be handled with appropriate privacy considerations according to your organization's policies and applicable regulations.", + "type": "string", + "examples": [ + "male" + ] + }, + "given_name": { + "description": "The user's given name (first name). This field stores the user's first name and is used for personalization, display purposes, and when generating the full display name. The given name appears in user interfaces, formal communications, and user listings throughout the system. Maximum 255 characters allowed.", + "type": "string", + "examples": [ + "John" + ] + }, + "groups": { + "description": "The list of group names the user belongs to within the organization. This field stores the user's group memberships for role-based access control, team assignments, and organizational structure. Groups are typically used for permission management, collaborative access, and organizational hierarchy. Each group name represents a distinct organizational unit or team that the user is associated with.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "admin", + "developer" + ] + ] + }, + "id": { + "description": "Unique system-generated identifier for the user profile. Immutable and read-only.", + "type": "string", + "readOnly": true, + "examples": [ + "usr_profile_1234abcd5678efgh" + ] + }, + "locale": { + "description": "The user's preferred language and region settings using BCP-47 format codes. This field customizes the user's experience with localized content, date formats, number formatting, and UI language throughout the system. When not specified, the user inherits the organization's default locale settings. Common values include `en-US`, `en-GB`, `fr-FR`, `de-DE`, and `es-ES`.", + "type": "string", + "examples": [ + "en-US" + ] + }, + "metadata": { + "description": "Raw attributes received from identity providers during authentication. This field stores the original user profile data as received from external IdP systems (SAML, OIDC, etc.) including provider-specific claims and attributes. These fields preserve the complete set of attributes received from the identity source and are used for mapping, synchronization, and audit purposes. Keys must be 3-25 characters, values must be 1-256 characters, with a maximum of 20 key-value pairs.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "department": "engineering", + "employee_type": "full-time", + "idp_user_id": "12345" + } + ] + }, + "name": { + "description": "The user's complete display name in formatted form. This field stores the full name as a single string and is typically used when you want to set the complete name rather than using separate given and family names. This name appears in user interfaces, reports, directory listings, and anywhere a formatted display name is needed. This field serves as a formatted display name that complements the individual given_name and family_name fields.", + "type": "string", + "examples": [ + "John Michael Doe" + ] + }, + "phone_number": { + "description": "The user's phone number in E.164 international format. This field stores the phone number for user contact and identification purposes. The phone number must include the country code and be formatted according to E.164 standards (e.g., `+1` for US numbers). This field is optional.", + "type": "string", + "examples": [ + "+14155552671" + ] + }, + "phone_number_verified": { + "description": "Indicates if the user's phone number has been verified. Automatically updated by the system.", + "type": "boolean", + "readOnly": true, + "examples": [ + true + ] + }, + "picture": { + "description": "The URL to the user's profile picture or avatar image. This field stores the location of the user's profile photo that appears in user interfaces, directory listings, and collaborative features throughout the system. The URL should point to a publicly accessible image file. Supported formats typically include JPEG, PNG, and GIF. This image is used for visual identification and personalization across the platform.", + "type": "string", + "examples": [ + "https://example.com/avatar.jpg" + ] + }, + "preferred_username": { + "description": "The user's preferred username for display and identification purposes. This field stores a custom username that the user prefers to be known by, which may differ from their email or formal name. This username appears in user interfaces, mentions, informal communications, and collaborative features throughout the system. Maximum 512 characters allowed.", + "type": "string", + "examples": [ + "johndoe" + ] + } + } + }, + "usersUser": { + "type": "object", + "properties": { + "create_time": { + "description": "Timestamp when the user account was initially created. Automatically set by the server.", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "email": { + "description": "Primary email address for the user. Must be unique across the environment and valid per RFC 5322.", + "type": "string", + "examples": [ + "user@example.com" + ] + }, + "external_id": { + "description": "Your application's unique identifier for this organization, used to link Scalekit with your system.", + "type": "string", + "examples": [ + "ext_12345a67b89c" + ] + }, + "id": { + "description": "Unique system-generated identifier for the user. Immutable once created.", + "type": "string", + "examples": [ + "usr_1234abcd5678efgh" + ] + }, + "last_login_time": { + "description": "Timestamp of the user's most recent successful authentication. Updated automatically.", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "memberships": { + "description": "List of organization memberships. Automatically populated based on group assignments.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/commonsOrganizationMembership" + } + }, + "metadata": { + "description": "Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars).", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "department": "engineering", + "location": "nyc-office" + } + ] + }, + "update_time": { + "description": "Timestamp of the last modification to the user account. Automatically updated by the server.", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "user_profile": { + "description": "User's personal information including name, address, and other profile attributes.", + "$ref": "#/components/schemas/commonsUserProfile" + } + } + }, + "usersCreateMembershipResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/usersUser" + } + } + }, + "v1usersUpdateMembership": { + "type": "object", + "properties": { + "metadata": { + "description": "Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars).", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "department": "engineering", + "location": "nyc-office" + } + ] + }, + "roles": { + "description": "Role to assign to the user within the organization", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/commonsRole" + }, + "examples": [ + [ + { + "name": "admin" + } + ] + ] + } + } + }, + "usersUpdateMembershipResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/usersUser" + } + } + }, + "commonsRegionCode": { + "type": "string", + "enum": [ + "US", + "EU" + ] + }, + "organizationsOrganizationSettingsFeature": { + "description": "Controls the activation state of a specific organization feature", + "type": "object", + "title": "Organization Feature Toggle", + "required": [ + "name", + "enabled" + ], + "properties": { + "enabled": { + "description": "Whether the feature is enabled (true) or disabled (false) for this organization", + "type": "boolean", + "examples": [ + true + ] + }, + "name": { + "description": "Feature identifier. Supported values include: \"sso\" (Single Sign-On), \"directory_sync\" (Directory Synchronization), \"domain_verification\" (Domain Verification)", + "type": "string", + "examples": [ + "sso" + ] + } + } + }, + "organizationsOrganizationSettings": { + "description": "Configuration options that control organization-level features and capabilities", + "type": "object", + "title": "Organization Settings", + "properties": { + "features": { + "description": "List of feature toggles that control organization capabilities such as SSO authentication and directory synchronization", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/organizationsOrganizationSettingsFeature" + }, + "examples": [ + [ + { + "enabled": true, + "name": "sso" + }, + { + "enabled": false, + "name": "directory_sync" + } + ] + ] + } + }, + "examples": [ + { + "features": [ + { + "enabled": true, + "name": "sso" + }, + { + "enabled": false, + "name": "directory_sync" + } + ] + } + ] + }, + "organizationsOrganization": { + "type": "object", + "required": [ + "create_time" + ], + "properties": { + "create_time": { + "description": "Timestamp when the organization was created", + "type": "string", + "format": "date-time", + "title": "Created Time", + "examples": [ + "2025-02-15T06:23:44.560000Z" + ] + }, + "display_name": { + "description": "Name of the organization. Must be between 1 and 200 characters", + "type": "string", + "title": "Name of the org to be used in display", + "examples": [ + "Megasoft" + ] + }, + "external_id": { + "description": "Your application's unique identifier for this organization, used to link Scalekit with your system.", + "type": "string", + "title": "External Id is useful to store a unique identifier for a given Org that. The unique Identifier can be the id of your tenant / org in your SaaSApp", + "examples": [ + "my_unique_id" + ] + }, + "id": { + "description": "Unique scalekit-generated identifier that uniquely references an organization", + "type": "string", + "title": "Id", + "examples": [ + "org_59615193906282635" + ] + }, + "metadata": { + "description": "Key value pairs extension attributes.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "region_code": { + "description": "Geographic region code for the organization. Currently limited to US.", + "title": "Optional regioncode", + "$ref": "#/components/schemas/commonsRegionCode", + "examples": [ + "US" + ] + }, + "settings": { + "title": "Organization Settings", + "$ref": "#/components/schemas/organizationsOrganizationSettings" + }, + "update_time": { + "description": "Timestamp when the organization was last updated", + "type": "string", + "format": "date-time", + "title": "Updated time", + "examples": [ + "2025-02-15T06:23:44.560000Z" + ] + } + } + }, + "organizationsListOrganizationsResponse": { + "type": "object", + "properties": { + "next_page_token": { + "description": "Pagination token for the next page of results. Use this token to fetch the next page.", + "type": "string", + "examples": [ + "" + ] + }, + "organizations": { + "description": "List of organization objects", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/organizationsOrganization" + } + }, + "prev_page_token": { + "description": "Pagination token for the previous page of results. Use this token to fetch the previous page.", + "type": "string", + "examples": [ + "" + ] + }, + "total_size": { + "description": "Total number of organizations in the environment.", + "type": "integer", + "format": "int64", + "examples": [ + 30 + ] + } + } + }, + "v1organizationsCreateOrganization": { + "type": "object", + "required": [ + "display_name" + ], + "properties": { + "display_name": { + "description": "Name of the organization. Must be between 1 and 200 characters.", + "type": "string", + "examples": [ + "Megasoft Inc" + ] + }, + "external_id": { + "description": "Your application's unique identifier for this organization, used to link Scalekit with your system.", + "type": "string", + "examples": [ + "my_unique_id" + ] + }, + "metadata": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "organizationsCreateOrganizationResponse": { + "type": "object", + "properties": { + "organization": { + "description": "The newly created organization containing its ID, settings, and metadata", + "$ref": "#/components/schemas/organizationsOrganization" + } + } + }, + "organizationsGetOrganizationResponse": { + "type": "object", + "properties": { + "organization": { + "description": "The newly created organization", + "$ref": "#/components/schemas/organizationsOrganization" + } + } + }, + "v1organizationsUpdateOrganization": { + "description": "For update messages ensure the indexes are same as the base model itself.", + "type": "object", + "properties": { + "display_name": { + "description": "Name of the organization to display in the UI. Must be between 1 and 200 characters", + "type": "string", + "examples": [ + "Acme Corporation" + ] + }, + "external_id": { + "description": "Your application's unique identifier for this organization, used to link Scalekit with your system", + "type": "string", + "examples": [ + "tenant_12345" + ] + }, + "metadata": { + "description": "Custom key-value pairs to store with the organization. Keys must be 3-25 characters, values must be 1-256 characters. Maximum 10 pairs allowed.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "industry": "technology" + } + ] + } + } + }, + "organizationsUpdateOrganizationResponse": { + "type": "object", + "properties": { + "organization": { + "description": "Updated organization details", + "$ref": "#/components/schemas/organizationsOrganization" + } + } + }, + "organizationsLink": { + "type": "object", + "properties": { + "expire_time": { + "description": "Expiry time of the link. The link is valid for 1 minute.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-02-06T14:48:00Z" + ] + }, + "id": { + "description": "Unique Identifier for the link", + "type": "string", + "examples": [ + "lnk_123123123123123" + ] + }, + "location": { + "description": "Location of the link. This is the URL that can be used to access the Admin portal. The link is valid for 1 minute", + "type": "string", + "examples": [ + "https://scalekit.com/portal/lnk_123123123123123" + ] + } + } + }, + "organizationsGeneratePortalLinkResponse": { + "type": "object", + "properties": { + "link": { + "description": "Contains the generated admin portal link details. The link URL can be shared with organization administrators to set up: Single Sign-On (SSO) authentication and directory synchronization", + "$ref": "#/components/schemas/organizationsLink" + } + } + }, + "rolesRolePermission": { + "type": "object", + "title": "RolePermissions represents a permission with role source information", + "properties": { + "create_time": { + "type": "string", + "format": "date-time" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "role_name": { + "description": "Name of the role from which this permission was sourced", + "type": "string", + "examples": [ + "admin_role" + ] + }, + "update_time": { + "type": "string", + "format": "date-time" + } + } + }, + "v1rolesRole": { + "type": "object", + "properties": { + "default_creator": { + "description": "Indicates if this role is the default creator role for new organizations.", + "type": "boolean", + "examples": [ + true + ] + }, + "default_member": { + "description": "Indicates if this role is the default member role for new users.", + "type": "boolean", + "examples": [ + true + ] + }, + "dependent_roles_count": { + "description": "Number of roles that extend from this role (dependent roles count). Read-only field.", + "type": "integer", + "format": "int32", + "examples": [ + 3 + ] + }, + "description": { + "description": "Detailed description of the role's purpose and capabilities. Maximum 2000 characters.", + "type": "string", + "examples": [ + "Can create, edit, and publish content but cannot delete or manage users" + ] + }, + "display_name": { + "description": "Human-readable display name for the role. Used in user interfaces and reports.", + "type": "string", + "examples": [ + "Content Editor" + ] + }, + "extends": { + "description": "Name of the base role that this role extends. Enables hierarchical role inheritance.", + "type": "string", + "examples": [ + "admin_role" + ] + }, + "id": { + "description": "Unique system-generated identifier for the role. Immutable once created.", + "type": "string", + "readOnly": true, + "examples": [ + "role_1234abcd5678efgh" + ] + }, + "is_org_role": { + "description": "Indicates if this role is an organization role.", + "type": "boolean", + "examples": [ + true + ] + }, + "name": { + "description": "Unique name identifier for the role. Must be alphanumeric with underscores, 1-100 characters.", + "type": "string", + "examples": [ + "content_editor" + ] + }, + "permissions": { + "description": "List of permissions with role source information. Only included when 'include' parameter is specified in the request.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/rolesRolePermission" + }, + "examples": [ + [ + { + "description": "Read Content", + "name": "read:content", + "role_name": "admin_role" + }, + { + "description": "Write Content", + "name": "write:content", + "role_name": "editor_role" + } + ] + ] + } + } + }, + "rolesListOrganizationRolesResponse": { + "type": "object", + "properties": { + "roles": { + "description": "List of roles objects", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/v1rolesRole" + } + } + } + }, + "v1rolesCreateOrganizationRole": { + "type": "object", + "properties": { + "description": { + "description": "Description of the organization's role", + "type": "string", + "examples": [ + "Organization Viewer Role will be used only for viewing the objects" + ] + }, + "display_name": { + "description": "Display name of the organization's role", + "type": "string", + "examples": [ + "Organization Viewer Role" + ] + }, + "extends": { + "description": "Base role name for hierarchical roles", + "type": "string", + "examples": [ + "admin_role" + ] + }, + "name": { + "description": "Unique name of the organization's role", + "type": "string", + "examples": [ + "org_viewer_role" + ] + }, + "permissions": { + "description": "List of permission names to assign to this role. Permissions must exist in the current environment.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "read:users", + "write:documents" + ] + ] + } + } + }, + "rolesCreateOrganizationRoleResponse": { + "type": "object", + "properties": { + "role": { + "$ref": "#/components/schemas/v1rolesRole" + } + } + }, + "rolesGetOrganizationRoleResponse": { + "type": "object", + "properties": { + "role": { + "$ref": "#/components/schemas/v1rolesRole" + } + } + }, + "v1rolesUpdateRole": { + "type": "object", + "properties": { + "description": { + "description": "Detailed description of the role's purpose, capabilities, and intended use cases. Maximum 2000 characters.", + "type": "string", + "examples": [ + "Can create, edit, publish, and approve content. Cannot delete content or manage user accounts." + ] + }, + "display_name": { + "description": "Human-readable display name for the role. Used in user interfaces, reports, and user-facing communications.", + "type": "string", + "examples": [ + "Senior Content Editor" + ] + }, + "extends": { + "description": "Name of the base role that this role extends. Enables hierarchical role inheritance where this role inherits all permissions from the base role.", + "type": "string", + "examples": [ + "content_editor" + ] + }, + "permissions": { + "description": "List of permission names to assign to this role. When provided, this replaces all existing role-permission mappings. Permissions must exist in the current environment. Maximum 100 permissions per role.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "read:content", + "write:content", + "publish:content", + "approve:content" + ] + ] + } + } + }, + "rolesUpdateOrganizationRoleResponse": { + "type": "object", + "properties": { + "role": { + "$ref": "#/components/schemas/v1rolesRole" + } + } + }, + "RolesServiceUpdateDefaultOrganizationRolesBody": { + "type": "object", + "properties": { + "default_member_role": { + "description": "Unique name of the default member role", + "type": "string", + "examples": [ + "member" + ] + } + } + }, + "rolesUpdateDefaultOrganizationRolesResponse": { + "type": "object", + "properties": { + "default_member": { + "description": "Updated default member role", + "$ref": "#/components/schemas/v1rolesRole", + "examples": [ + { + "description": "Role for regular members", + "display_name": "Member Role", + "id": "role_0987654321", + "name": "member" + } + ] + } + } + }, + "clientsCustomClaim": { + "type": "object", + "properties": { + "key": { + "description": "The name of the custom claim. Must be between 1 and 128 characters. Use descriptive names that clearly indicate the claim's purpose.", + "type": "string", + "examples": [ + "environment" + ] + }, + "value": { + "description": "The value of the custom claim. This value will be included in access tokens issued to the client.", + "type": "string", + "examples": [ + "production" + ] + } + } + }, + "clientsClientSecretStatus": { + "description": "ClientSecretStatus indicates whether a client secret can be used for authentication.\nACTIVE secrets can be used for authentication while INACTIVE secrets cannot.\n\n - INACTIVE: The secret is inactive and cannot be used for authentication", + "type": "string", + "enum": [ + "INACTIVE" + ] + }, + "clientsClientSecret": { + "description": "A secure credential used for authenticating an API client. Each client can have multiple secrets for key rotation purposes.", + "type": "object", + "title": "Client Secret", + "properties": { + "create_time": { + "description": "The timestamp when this secret was created. This field is automatically set by the server and cannot be modified.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-01-05T14:48:00Z" + ] + }, + "created_by": { + "description": "The identifier of the user or system that created this secret. This field helps track who created the secret for audit and compliance purposes.", + "type": "string", + "examples": [ + "user_12345" + ] + }, + "expire_time": { + "description": "The timestamp when this secret will expire. After this time, the secret cannot be used for authentication regardless of its status. If not set, the secret does not expire.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-05T14:48:00Z" + ] + }, + "id": { + "description": "The unique identifier for this client secret. This ID is used to reference the secret in API requests for management operations like updating or deleting the secret.", + "type": "string", + "examples": [ + "sec_1234abcd5678efgh" + ] + }, + "last_used_time": { + "description": "The timestamp when this secret was last used for authentication. This field helps track secret usage for security monitoring and identifying unused secrets that may be candidates for rotation.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-02-15T10:30:00Z" + ] + }, + "plain_secret": { + "description": "The full plaintext secret value. This field is only populated when the secret is first created and is never stored by the server. It must be securely stored by the client application as it cannot be retrieved again.", + "type": "string", + "examples": [ + "sec_1234567890abcdefghijklmnopqrstuvwxyz" + ] + }, + "secret_suffix": { + "description": "A suffix that helps identify this secret. This is the last few characters of the full secret value but is not sufficient for authentication. Helps identify which secret is being used in logs and debugging.", + "type": "string", + "examples": [ + "xyzw" + ] + }, + "status": { + "description": "The current status of this secret. A secret must be ACTIVE to be used for authentication. INACTIVE secrets cannot be used for authentication but are retained for audit purposes.", + "$ref": "#/components/schemas/clientsClientSecretStatus", + "examples": [ + "INACTIVE" + ] + }, + "update_time": { + "description": "The timestamp when this secret was last updated. This field is automatically updated by the server when the secret's status changes or other properties are modified.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-01-10T09:12:00Z" + ] + } + } + }, + "clientsM2MClient": { + "type": "object", + "properties": { + "audience": { + "description": "The intended recipients of access tokens issued to this client. Each audience value should be a URI that identifies an API or service.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "https://api.example.com" + ] + ] + }, + "client_id": { + "description": "The unique identifier for this API client. This ID is used to identify the client in API requests and logs. It is automatically generated when the client is created and cannot be modified.", + "type": "string", + "examples": [ + "m2morg_1231234233424344" + ] + }, + "create_time": { + "description": "The timestamp when this API client was created. This field is automatically set by the server and cannot be modified.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-01-05T14:48:00Z" + ] + }, + "custom_claims": { + "description": "Additional claims included in access tokens issued to this client. These claims provide context about the client and can be used for authorization decisions.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/clientsCustomClaim" + } + }, + "description": { + "description": "A detailed description of the client's purpose and usage. This helps administrators understand what the client is used for.", + "type": "string", + "examples": [ + "Service account for automated deployment processes" + ] + }, + "expiry": { + "description": "Expiry time in seconds for the token generated by the client", + "type": "string", + "format": "int64", + "examples": [ + 3600 + ] + }, + "is_cimd": { + "description": "Indicates if the client was created via Client ID Metadata Document (CIMD). CIMD clients can update their own configuration according to the CIMD specification.", + "type": "boolean", + "examples": [ + false + ] + }, + "is_dcr": { + "description": "Indicates if the client was created via Dynamic Client Registration (DCR). Clients created through DCR may have different management and lifecycle policies compared to those created manually.", + "type": "boolean", + "examples": [ + false + ] + }, + "metadata_uri": { + "description": "The URI to the client's metadata, which is utilized to obtain the client's configuration details", + "type": "string", + "examples": [ + "https://example.com/client-metadata.json" + ] + }, + "name": { + "description": "The display name of the API client. This name helps identify the client in the dashboard and logs.", + "type": "string", + "examples": [ + "GitHub Actions Deployment Service" + ] + }, + "organization_id": { + "description": "The ID of the organization that owns this API client. This ID is used to associate the client with the correct organization and enforce organization-specific access controls.", + "type": "string", + "examples": [ + "org_1231234233424344" + ] + }, + "redirect_uris": { + "description": "The redirect URI for this API client. This URI is used in the OAuth 2.0 authorization flow to redirect users after authentication.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "https://example.com/callback" + ] + ] + }, + "resource_id": { + "description": "The ID of the resource associated with this M2M client. This field is used to link the client to a specific resource in the system.", + "type": "string", + "examples": [ + "app_1231234233424344" + ] + }, + "scopes": { + "description": "The OAuth 2.0 scopes granted to this client. These scopes determine what resources and actions the client can access.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "deploy:resources", + "read:deployments" + ] + ] + }, + "secrets": { + "description": "List of client secrets associated with this client. Each secret can be used for authentication, but only the most recently created secret is typically active. Secrets are stored securely and their values are never returned after creation.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/clientsClientSecret" + } + }, + "update_time": { + "description": "The timestamp when this API client was last updated. This field is automatically updated by the server whenever the client's configuration changes.", + "type": "string", + "format": "date-time", + "examples": [ + "2024-01-05T14:48:00Z" + ] + } + } + }, + "clientsListOrganizationClientsResponse": { + "description": "Response message containing a paginated list of API clients for the specified organization.", + "type": "object", + "title": "List Organization Clients Response", + "properties": { + "clients": { + "description": "List of API client objects for the organization. Each client includes its configuration, metadata, and active secrets (without exposing actual secret values).", + "type": "array", + "title": "List of organization API clients", + "items": { + "type": "object", + "$ref": "#/components/schemas/clientsM2MClient" + } + }, + "next_page_token": { + "description": "Pagination token for the next page of results. Use this token to fetch the next page.", + "type": "string", + "title": "Pagination token for the next page of results", + "examples": [ + "" + ] + }, + "prev_page_token": { + "description": "Pagination token for the previous page of results. Use this token to fetch the previous page.", + "type": "string", + "title": "Pagination token for the previous page of results", + "examples": [ + "" + ] + }, + "total_size": { + "description": "Total number of API clients in the organization.", + "type": "integer", + "format": "int64", + "title": "Total number of clients in the organization", + "examples": [ + 30 + ] + } + } + }, + "clientsOrganizationClient": { + "type": "object", + "properties": { + "audience": { + "description": "The intended recipients of the access tokens issued to this client. Each audience value should be a URI that identifies the API or service that will validate the token.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "https://api.example.com/api/analytics", + "https://deployment-api.acmecorp.com" + ] + ] + }, + "custom_claims": { + "description": "Additional claims to be included in access tokens issued to this client. These claims provide context about the client and can be used for authorization decisions. Keep claims minimal to avoid increasing token size.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/clientsCustomClaim" + }, + "examples": [ + [ + { + "key": "environment", + "value": "production" + }, + { + "key": "service", + "value": "deployment" + } + ] + ] + }, + "description": { + "description": "A detailed explanation of the client's purpose and usage. This helps administrators understand what the client is used for and who manages it.", + "type": "string", + "examples": [ + "Service account for GitHub Actions to deploy resources to production" + ] + }, + "expiry": { + "description": "Expiry time in seconds for the token generated by the client", + "type": "string", + "format": "int64", + "examples": [ + 3600 + ] + }, + "name": { + "description": "A descriptive name for the API client that helps identify its purpose. This name is displayed in the dashboard and logs. Must be between 1 and 128 characters.", + "type": "string", + "examples": [ + "GitHub Actions Deployment Service" + ] + }, + "scopes": { + "description": "OAuth 2.0 scopes that define the permissions granted to this client. Each scope represents a specific permission or set of permissions. The client can only access resources that match its granted scopes.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "deploy:resources", + "read:deployments" + ] + ] + } + } + }, + "clientsCreateOrganizationClientResponse": { + "type": "object", + "properties": { + "client": { + "description": "Details of the created client", + "$ref": "#/components/schemas/clientsM2MClient" + }, + "plain_secret": { + "description": "Client secret value (only returned once at creation)", + "type": "string", + "examples": [ + "CdExsdErfccxDDssddfffgfeFHH1" + ] + } + } + }, + "clientsGetOrganizationClientResponse": { + "type": "object", + "properties": { + "client": { + "description": "Details of the requested client", + "$ref": "#/components/schemas/clientsM2MClient" + } + } + }, + "clientsUpdateOrganizationClientResponse": { + "type": "object", + "properties": { + "client": { + "description": "Updated details of the client", + "$ref": "#/components/schemas/clientsM2MClient" + } + } + }, + "clientsCreateOrganizationClientSecretResponse": { + "type": "object", + "properties": { + "plain_secret": { + "description": "Client secret value (only returned once at creation)", + "type": "string", + "examples": [ + "m2morg_client_secret_xyz123" + ] + }, + "secret": { + "description": "Details of the created client secret", + "$ref": "#/components/schemas/clientsClientSecret" + } + } + }, + "connectionsConfigurationType": { + "type": "string", + "enum": [ + "DISCOVERY", + "MANUAL" + ] + }, + "domainsVerificationMethod": { + "type": "string", + "enum": [ + "ADMIN", + "DNS", + "NOT_APPLICABLE" + ] + }, + "domainsVerificationStatus": { + "type": "string", + "enum": [ + "PENDING", + "VERIFIED", + "FAILED", + "AUTO_VERIFIED" + ] + }, + "domainsDomain": { + "type": "object", + "properties": { + "create_time": { + "description": "Timestamp when the domain was first created.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-09-01T12:14:43.100000Z" + ] + }, + "domain": { + "description": "The business domain name that was configured for allowed email domain functionality (e.g., company.com, subdomain.company.com).", + "type": "string", + "examples": [ + "customerdomain.com" + ] + }, + "domain_type": { + "example": "ORGANIZATION_DOMAIN" + }, + "environment_id": { + "description": "The environment ID where this domain is configured.", + "type": "string", + "examples": [ + "env_58345499215790610" + ] + }, + "id": { + "description": "Scalekit-generated unique identifier for this domain record.", + "type": "string", + "examples": [ + "dom_88351643129225005" + ] + }, + "organization_id": { + "description": "The organization to which the domain belongs.", + "type": "string", + "examples": [ + "org_81667076086825451" + ] + }, + "update_time": { + "description": "Timestamp when the domain was last updated.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-09-01T12:14:43.110455Z" + ] + }, + "verification_method": { + "description": "Method that determines how domain ownership is verified.\n- ADMIN: domain is marked verified without DNS validation, typically by an admin.\n- DNS: domain must be verified by adding a TXT record to your DNS configuration.\n- NOT_APPLICABLE: verification does not apply to this domain type.", + "$ref": "#/components/schemas/domainsVerificationMethod", + "examples": [ + "ADMIN" + ] + }, + "verification_status": { + "description": "Verification status of the domain.\n- PENDING: DNS TXT record has not been validated yet.\n- VERIFIED: domain confirmed via DNS TXT record validation or admin approval.\n- AUTO_VERIFIED: domain verified automatically without DNS changes.\n- FAILED: DNS TXT record was not validated within the verification window.", + "$ref": "#/components/schemas/domainsVerificationStatus", + "examples": [ + "AUTO_VERIFIED" + ] + } + } + }, + "connectionsOAuthConnectionConfig": { + "type": "object", + "properties": { + "access_type": { + "description": "Access Type", + "type": "string", + "examples": [ + "offline" + ] + }, + "authorize_uri": { + "description": "Authorize URI", + "type": "string", + "examples": [ + "https://youridp.com/service/oauth/authorize" + ] + }, + "client_id": { + "description": "Client ID", + "type": "string", + "examples": [ + "oauth_client_id" + ] + }, + "client_secret": { + "description": "Client Secret", + "type": "string", + "examples": [ + "oauth_client_secret" + ] + }, + "custom_scope_name": { + "description": "Custom Scope Name", + "type": "string", + "examples": [ + "user_scope" + ] + }, + "pkce_enabled": { + "description": "PKCE Enabled", + "type": "boolean", + "examples": [ + true + ] + }, + "prompt": { + "description": "Prompt for the user", + "type": "string", + "examples": [ + "none" + ] + }, + "redirect_uri": { + "description": "Redirect URI", + "type": "string", + "examples": [ + "https://yourapp.com/service/oauth/redirect" + ] + }, + "scopes": { + "description": "OIDC Scopes", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "openid", + "profile" + ] + ] + }, + "sync_user_profile_on_login": { + "description": "Indicates whether user profiles should be synchronized with the identity provider upon each log-in.", + "type": "boolean", + "examples": [ + true + ] + }, + "tenant_id": { + "description": "Microsoft Entra tenant ID. Required when using a single-tenant or multi-tenant app registered in Microsoft Entra. Leave empty to use the common endpoint.", + "type": "string", + "examples": [ + "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + ] + }, + "token_access_type": { + "description": "Token Access Type", + "type": "string", + "examples": [ + "offline" + ] + }, + "token_uri": { + "description": "Token URI", + "type": "string", + "examples": [ + "https://youridp.com/service/oauth/token" + ] + }, + "use_platform_creds": { + "description": "Use Scalekit credentials", + "type": "boolean", + "examples": [ + true + ] + }, + "user_info_uri": { + "description": "User Info URI", + "type": "string", + "examples": [ + "https://youridp.com/service/oauth/userinfo" + ] + } + } + }, + "connectionsOIDCScope": { + "type": "string", + "enum": [ + "openid", + "profile", + "email", + "address", + "phone" + ] + }, + "connectionsTokenAuthType": { + "type": "string", + "enum": [ + "URL_PARAMS", + "BASIC_AUTH" + ] + }, + "connectionsOIDCConnectionConfig": { + "type": "object", + "properties": { + "authorize_uri": { + "description": "Authorize URI", + "type": "string", + "examples": [ + "https://youridp.com/service/oauth/authorize" + ] + }, + "backchannel_logout_redirect_uri": { + "description": "backchannel logout redirect uri where idp sends logout_token", + "type": "string", + "readOnly": true, + "examples": [ + "https://yourapp.com/sso/v1/oidc/conn_1234/backchannel-logout" + ] + }, + "client_id": { + "description": "Client ID", + "type": "string", + "examples": [ + "oauth_client_id" + ] + }, + "client_secret": { + "description": "Client Secret", + "type": "string", + "examples": [ + "oauth_client_secret" + ] + }, + "discovery_endpoint": { + "description": "Discovery Endpoint", + "type": "string", + "examples": [ + "https://youridp.com/service/oauth/.well-known/openid-configuration" + ] + }, + "idp_logout_required": { + "description": "Enable IDP logout", + "type": "boolean", + "examples": [ + true + ] + }, + "issuer": { + "description": "Issuer URL", + "type": "string", + "examples": [ + "https://youridp.com/service/oauth" + ] + }, + "jit_provisioning_with_sso_enabled": { + "description": "Indicates if Just In Time user provisioning is enabled for the connection", + "type": "boolean", + "examples": [ + true + ] + }, + "jwks_uri": { + "description": "JWKS URI", + "type": "string", + "examples": [ + "https://youridp.com/service/oauth/jwks" + ] + }, + "pkce_enabled": { + "description": "PKCE Enabled", + "type": "boolean", + "examples": [ + true + ] + }, + "post_logout_redirect_uri": { + "description": "post logout redirect uri", + "type": "string", + "readOnly": true, + "examples": [ + "https://yourapp.com/sso/v1/oidc/conn_1234/logout/callback" + ] + }, + "redirect_uri": { + "description": "Redirect URI", + "type": "string", + "examples": [ + "https://yourapp.com/sso/v1/oidc/conn_1234/callback" + ] + }, + "scopes": { + "description": "OIDC Scopes", + "type": "array", + "items": { + "$ref": "#/components/schemas/connectionsOIDCScope" + }, + "examples": [ + [ + "openid", + "profile" + ] + ] + }, + "sync_user_profile_on_login": { + "description": "Indicates whether user profiles should be synchronized with the identity provider upon each log-in.", + "type": "boolean", + "examples": [ + true + ] + }, + "token_auth_type": { + "description": "Token Auth Type", + "$ref": "#/components/schemas/connectionsTokenAuthType", + "examples": [ + "URL_PARAMS" + ] + }, + "token_uri": { + "description": "Token URI", + "type": "string", + "examples": [ + "https://youridp.com/service/oauth/token" + ] + }, + "user_info_uri": { + "description": "User Info URI", + "type": "string", + "examples": [ + "https://youridp.com/service/oauth/userinfo" + ] + } + } + }, + "connectionsCodeChallengeType": { + "type": "string", + "enum": [ + "NUMERIC", + "ALPHANUMERIC" + ] + }, + "connectionsPasswordlessType": { + "type": "string", + "enum": [ + "LINK", + "OTP", + "LINK_OTP" + ] + }, + "connectionsPasswordLessConfig": { + "type": "object", + "properties": { + "code_challenge_length": { + "description": "Code Challenge Length", + "type": "integer", + "format": "int64", + "examples": [ + 6 + ] + }, + "code_challenge_type": { + "description": "Code Challenge Type", + "$ref": "#/components/schemas/connectionsCodeChallengeType", + "examples": [ + "NUMERIC" + ] + }, + "enforce_same_browser_origin": { + "description": "Enforce Same Browser Origin", + "type": "boolean", + "examples": [ + true + ] + }, + "frequency": { + "description": "Link Frequency", + "type": "integer", + "format": "int64", + "examples": [ + 1 + ] + }, + "regenerate_passwordless_credentials_on_resend": { + "description": "Regenerate the ", + "type": "boolean", + "examples": [ + true + ] + }, + "type": { + "description": "Passwordless Type", + "$ref": "#/components/schemas/connectionsPasswordlessType", + "examples": [ + "LINK" + ] + }, + "validity": { + "description": "Link Validity in Seconds", + "type": "integer", + "format": "int64", + "examples": [ + 600 + ] + } + } + }, + "connectionsIDPCertificate": { + "type": "object", + "properties": { + "certificate": { + "description": "IDP Certificate", + "type": "string" + }, + "create_time": { + "description": "Certificate Creation Time", + "type": "string", + "format": "date-time", + "examples": [ + "2021-09-01T00:00:00Z" + ] + }, + "expiry_time": { + "description": "Certificate Expiry Time", + "type": "string", + "format": "date-time", + "examples": [ + "2021-09-01T00:00:00Z" + ] + }, + "id": { + "description": "Certificate ID", + "type": "string", + "examples": [ + "cert_123123123123" + ] + }, + "issuer": { + "description": "Certificate Issuer", + "type": "string", + "examples": [ + "https://youridp.com/service/saml" + ] + } + } + }, + "connectionsNameIdFormat": { + "type": "string", + "enum": [ + "UNSPECIFIED", + "EMAIL", + "TRANSIENT", + "PERSISTENT" + ] + }, + "connectionsRequestBinding": { + "type": "string", + "enum": [ + "HTTP_POST", + "HTTP_REDIRECT" + ] + }, + "connectionsSAMLSigningOptions": { + "type": "string", + "title": "enums all", + "enum": [ + "NO_SIGNING", + "SAML_ONLY_RESPONSE_SIGNING", + "SAML_ONLY_ASSERTION_SIGNING", + "SAML_RESPONSE_ASSERTION_SIGNING", + "SAML_RESPONSE_OR_ASSERTION_SIGNING" + ] + }, + "connectionsSAMLConnectionConfigResponse": { + "type": "object", + "properties": { + "allow_idp_initiated_login": { + "description": "Allow IDP Initiated Login", + "type": "boolean", + "examples": [ + true + ] + }, + "assertion_encrypted": { + "description": "Assertion Encrypted", + "type": "boolean", + "examples": [ + true + ] + }, + "certificate_id": { + "description": "Certificate ID", + "type": "string", + "examples": [ + "cer_35585423166144613" + ] + }, + "default_redirect_uri": { + "description": "Default Redirect URI", + "type": "string", + "examples": [ + "https://yourapp.com/service/saml/redirect" + ] + }, + "force_authn": { + "description": "Force Authn", + "type": "boolean", + "examples": [ + true + ] + }, + "idp_certificates": { + "description": "IDP Certificates", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/connectionsIDPCertificate" + } + }, + "idp_entity_id": { + "description": "IDP Entity ID", + "type": "string", + "examples": [ + "https://youridp.com/service/saml" + ] + }, + "idp_metadata_url": { + "description": "IDP Metadata URL", + "type": "string", + "examples": [ + "https://youridp.com/service/saml/metadata" + ] + }, + "idp_name_id_format": { + "description": "IDP Name ID Format", + "$ref": "#/components/schemas/connectionsNameIdFormat", + "examples": [ + "EMAIL" + ] + }, + "idp_slo_request_binding": { + "description": "IDP SLO Request Binding", + "$ref": "#/components/schemas/connectionsRequestBinding", + "examples": [ + "HTTP_POST" + ] + }, + "idp_slo_required": { + "description": "Enable IDP logout", + "type": "boolean", + "examples": [ + true + ] + }, + "idp_slo_url": { + "description": "IDP SLO URL", + "type": "string", + "examples": [ + "https://youridp.com/service/saml/slo" + ] + }, + "idp_sso_request_binding": { + "description": "IDP SSO Request Binding", + "$ref": "#/components/schemas/connectionsRequestBinding", + "examples": [ + "HTTP_POST" + ] + }, + "idp_sso_url": { + "description": "IDP SSO URL", + "type": "string", + "examples": [ + "https://youridp.com/service/saml/sso" + ] + }, + "jit_provisioning_with_sso_enabled": { + "description": "Indicates if Just In Time user provisioning is enabled for the connection", + "type": "boolean", + "examples": [ + true + ] + }, + "saml_signing_option": { + "description": "SAML Signing Option", + "$ref": "#/components/schemas/connectionsSAMLSigningOptions", + "examples": [ + "SAML_ONLY_RESPONSE_SIGNING" + ] + }, + "sp_assertion_url": { + "description": "SP Assertion URL", + "type": "string", + "examples": [ + "https://youridp.com/service/saml/assertion" + ] + }, + "sp_entity_id": { + "description": "SP Entity ID", + "type": "string", + "examples": [ + "https://yourapp.com/service/saml" + ] + }, + "sp_metadata_url": { + "description": "SP Metadata URL", + "type": "string", + "examples": [ + "https://youridp.com/service/saml/metadata" + ] + }, + "sp_slo_url": { + "description": "Service Provider SLO url", + "type": "string", + "readOnly": true, + "examples": [ + "https://yourapp.com/sso/v1/saml/conn_1234/slo/callback" + ] + }, + "sync_user_profile_on_login": { + "description": "Indicates whether user profiles should be synchronized with the identity provider upon each log-in.", + "type": "boolean", + "examples": [ + true + ] + }, + "ui_button_title": { + "description": "UI Button Title", + "type": "string", + "examples": [ + "Login with SSO" + ] + }, + "want_request_signed": { + "description": "Want Request Signed", + "type": "boolean", + "examples": [ + true + ] + } + } + }, + "connectionsStaticAuthConfig": { + "type": "object", + "properties": { + "static_config": { + "type": "object" + } + } + }, + "WebAuthConfigurationAttestation": { + "type": "object", + "title": "Attestation preferences for registration", + "properties": { + "conveyance_preference": { + "type": "string", + "title": "Conveyance preference" + }, + "enterprise_approved_ids": { + "type": "array", + "title": "Enterprise-approved IDs (optional allowlist when enterprise attestation is used)", + "items": { + "type": "string" + } + } + } + }, + "WebAuthConfigurationAuthenticatorSelection": { + "type": "object", + "properties": { + "authenticator_attachment": { + "type": "string" + }, + "user_verification": { + "type": "string", + "title": "User verification requirement" + } + } + }, + "WebAuthConfigurationAuthenticators": { + "type": "object", + "properties": { + "desired_authenticator_status": { + "description": "provides the list of statuses which are considered undesirable for status report validation purposes. Should be used with validate_status set to true.", + "type": "array", + "items": { + "type": "string", + "default": "[]" + } + }, + "undesired_authenticator_status": { + "description": "provides the list of statuses which are considered undesirable for status report validation purposes. Should be used with validate_status set to true.", + "type": "array", + "items": { + "type": "string", + "default": "['ATTESTATION_KEY_COMPROMISE', 'USER_VERIFICATION_BYPASS', 'USER_KEY_REMOTE_COMPROMISE', 'USER_KEY_PHYSICAL_COMPROMISE', 'REVOKED']" + } + }, + "validate_anchors": { + "description": "when set to true enables the validation of the attestation statement against the trust anchor from the metadata statement.", + "type": "boolean" + }, + "validate_attestation_type": { + "description": "when set to true enables the validation of the attestation statements type against the known types the authenticator can produce.", + "type": "boolean" + }, + "validate_entry": { + "description": "requires that the provided metadata has an entry for the given authenticator to be considered valid. By default an AAGUID which has a zero value should fail validation if validate_entry_permit_zero_aaguid is not provided with the value of true.", + "type": "boolean" + }, + "validate_entry_permit_zero_aaguid": { + "description": "is an option that permits a zero'd AAGUID from an attestation statement to automatically pass metadata validations. Generally helpful to use with validate_entry.", + "type": "boolean" + }, + "validate_status": { + "description": "when set to true enables the validation of the attestation statements AAGUID against the desired and undesired lists", + "type": "boolean" + } + } + }, + "WebAuthConfigurationRp": { + "type": "object", + "title": "Rp contains relying party identifiers and origins", + "properties": { + "ids": { + "type": "array", + "title": "Relying party IDs (derived from environment domain and verified custom domain)\nAt least one required; must be hostnames without scheme or path", + "items": { + "type": "string" + } + }, + "origins": { + "type": "array", + "title": "Allowed origins corresponding to the RP IDs (https://)\nAt least one required; must be HTTPS origins", + "items": { + "type": "string" + } + } + } + }, + "WebAuthConfigurationTimeout": { + "type": "object", + "properties": { + "login": { + "description": "Login timeout duration", + "type": "string", + "default": "\"300s\"" + }, + "login_uvd": { + "description": "Login timeout duration when user verification is discouraged", + "type": "string", + "default": "\"300s\"" + }, + "registration": { + "description": "Registration timeout duration", + "type": "string", + "default": "\"300s\"" + }, + "registration_uvd": { + "description": "Registration timeout duration when user verification is discouraged", + "type": "string", + "default": "\"300s\"" + } + } + }, + "connectionsWebAuthConfiguration": { + "type": "object", + "title": "WebAuthConfiguration defines WebAuthn (passkeys) configuration limited to RP and Attestation", + "properties": { + "attestation": { + "$ref": "#/components/schemas/WebAuthConfigurationAttestation" + }, + "authenticator_selection": { + "$ref": "#/components/schemas/WebAuthConfigurationAuthenticatorSelection" + }, + "authenticators": { + "$ref": "#/components/schemas/WebAuthConfigurationAuthenticators" + }, + "enable_auto_registration": { + "description": "Enable auto registration for WebAuthn", + "type": "boolean" + }, + "enable_conditional_login": { + "description": "Allow autofill of passkeys in login page", + "type": "boolean" + }, + "rp": { + "$ref": "#/components/schemas/WebAuthConfigurationRp" + }, + "show_passkey_button": { + "description": "Show passkey button on login screen", + "type": "boolean" + }, + "timeout": { + "$ref": "#/components/schemas/WebAuthConfigurationTimeout" + } + } + }, + "connectionsConnection": { + "type": "object", + "properties": { + "attribute_mapping": { + "description": "Maps identity provider attributes to user profile fields. For example, {'email': 'user.mail', 'name': 'user.displayName'}.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "configuration_type": { + "description": "How the connection was configured: DISCOVERY (automatic configuration) or MANUAL (administrator configured)", + "$ref": "#/components/schemas/connectionsConfigurationType", + "examples": [ + "MANUAL" + ] + }, + "debug_enabled": { + "description": "Enables testing mode that allows non-HTTPS endpoints. Should only be enabled in development environments, never in production.", + "type": "boolean", + "examples": [ + true + ] + }, + "domains": { + "description": "Domain associated with this connection, used for domain-based authentication flows.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/domainsDomain" + }, + "examples": [ + [ + { + "name": "example.com" + } + ] + ] + }, + "enabled": { + "description": "Controls whether users can sign in using this connection. When false, the connection exists but cannot be used for authentication.", + "type": "boolean", + "examples": [ + false + ] + }, + "id": { + "description": "Unique identifier for this connection. Used in API calls to reference this specific connection.", + "type": "string", + "examples": [ + "conn_2123312131125533" + ] + }, + "key_id": { + "description": "Alternative identifier for this connection, typically used in frontend applications or URLs.", + "type": "string" + }, + "oauth_config": { + "description": "Configuration details for OAuth connections. Present only when type is OAUTH.", + "$ref": "#/components/schemas/connectionsOAuthConnectionConfig" + }, + "oidc_config": { + "description": "Configuration details for OpenID Connect (OIDC) connections. Present only when type is OIDC.", + "$ref": "#/components/schemas/connectionsOIDCConnectionConfig" + }, + "organization_id": { + "description": "Identifier of the organization that owns this connection. Connections are typically scoped to a single organization.", + "type": "string", + "examples": [ + "org_2123312131125533" + ] + }, + "passwordless_config": { + "description": "Configuration details for Magic Link authentication. Present only when type is MAGIC_LINK.", + "$ref": "#/components/schemas/connectionsPasswordLessConfig" + }, + "provider": { + "description": "Identity provider service that handles authentication (such as OKTA, Google, Azure AD, or a custom provider)", + "$ref": "#/components/schemas/connectionsConnectionProvider", + "examples": [ + "OKTA" + ] + }, + "provider_key": { + "description": "Key ID of the identity provider service that handles authentication", + "type": "string", + "examples": [ + "google" + ] + }, + "saml_config": { + "description": "Configuration details for SAML connections. Present only when type is SAML.", + "$ref": "#/components/schemas/connectionsSAMLConnectionConfigResponse" + }, + "static_config": { + "description": "Static configuration for custom connections. Present only when type is BASIC, BEARER, API_KEY, or custom.", + "$ref": "#/components/schemas/connectionsStaticAuthConfig" + }, + "status": { + "description": "Current configuration status of the connection. Possible values include IN_PROGRESS, CONFIGURED, and ERROR.", + "$ref": "#/components/schemas/connectionsConnectionStatus", + "readOnly": true, + "examples": [ + "IN_PROGRESS" + ] + }, + "test_connection_uri": { + "description": "URI that can be used to test this connection. Visit this URL to verify the connection works correctly.", + "type": "string", + "examples": [ + "https://auth.example.com/test-connection/conn_2123312131125533" + ] + }, + "type": { + "description": "Authentication protocol used by this connection. Can be OIDC (OpenID Connect), SAML, OAUTH, or MAGIC_LINK.", + "$ref": "#/components/schemas/connectionsConnectionType", + "examples": [ + "OIDC" + ] + }, + "webauthn_config": { + "description": "Configuration details for WebAuthn (passkeys). Present only when type is WEBAUTHN.", + "$ref": "#/components/schemas/connectionsWebAuthConfiguration" + } + } + }, + "connectionsGetConnectionResponse": { + "type": "object", + "properties": { + "connection": { + "description": "Complete connection details including provider configuration, protocol settings, status, and all metadata. Contains everything needed to understand the connection's current state.", + "$ref": "#/components/schemas/connectionsConnection" + } + } + }, + "connectionsToggleConnectionResponse": { + "type": "object", + "properties": { + "enabled": { + "description": "Current state of the connection after the operation. True means the connection is now enabled and can be used for authentication.", + "type": "boolean", + "examples": [ + true + ] + }, + "error_message": { + "description": "Error message if the operation fails", + "type": "string", + "examples": [ + "placeholder" + ] + } + } + }, + "directoriesAttributeMapping": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "map_to": { + "type": "string" + } + } + }, + "directoriesAttributeMappings": { + "type": "object", + "properties": { + "attributes": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/directoriesAttributeMapping" + } + } + } + }, + "directoriesDirectoryProvider": { + "type": "string", + "enum": [ + "OKTA", + "GOOGLE", + "MICROSOFT_AD", + "AUTH0", + "ONELOGIN", + "JUMPCLOUD", + "PING_IDENTITY" + ] + }, + "directoriesDirectoryType": { + "type": "string", + "enum": [ + "SCIM", + "LDAP", + "POLL" + ] + }, + "directoriesRoleAssignment": { + "type": "object", + "properties": { + "group_id": { + "description": "group ID for the role mapping", + "type": "string", + "examples": [ + "dirgroup_121312434123" + ] + }, + "role_name": { + "type": "string" + } + } + }, + "directoriesRoleAssignments": { + "type": "object", + "properties": { + "assignments": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/directoriesRoleAssignment" + } + } + } + }, + "directoriesSecretStatus": { + "type": "string", + "enum": [ + "INACTIVE" + ] + }, + "directoriesSecret": { + "type": "object", + "properties": { + "create_time": { + "description": "Creation Time", + "type": "string", + "format": "date-time", + "examples": [ + "2024-10-01T00:00:00Z" + ] + }, + "directory_id": { + "description": "Directory ID", + "type": "string", + "examples": [ + "dir_12362474900684814" + ] + }, + "expire_time": { + "description": "Expiry Time", + "type": "string", + "format": "date-time", + "examples": [ + "2025-10-01T00:00:00Z" + ] + }, + "id": { + "type": "string" + }, + "last_used_time": { + "description": "Last Used Time", + "type": "string", + "format": "date-time", + "examples": [ + "2024-10-01T00:00:00Z" + ] + }, + "secret_suffix": { + "description": "Secret Suffix", + "type": "string", + "examples": [ + "Nzg5" + ] + }, + "status": { + "description": "Secret Status", + "$ref": "#/components/schemas/directoriesSecretStatus", + "examples": [ + "INACTIVE" + ] + } + } + }, + "directoriesStats": { + "type": "object", + "properties": { + "group_updated_at": { + "description": "Max time of Group Updated At for Directory", + "type": "string", + "format": "date-time", + "examples": [ + "2024-10-01T00:00:00Z" + ] + }, + "total_groups": { + "description": "Total Groups in the Directory", + "type": "integer", + "format": "int32", + "examples": [ + 10 + ] + }, + "total_users": { + "description": "Total Users in the Directory", + "type": "integer", + "format": "int32", + "examples": [ + 10 + ] + }, + "user_updated_at": { + "description": "Max time of User Updated At for Directory", + "type": "string", + "format": "date-time", + "examples": [ + "2024-10-01T00:00:00Z" + ] + } + } + }, + "directoriesDirectory": { + "type": "object", + "properties": { + "attribute_mappings": { + "description": "Mappings between directory attributes and Scalekit user and group attributes", + "$ref": "#/components/schemas/directoriesAttributeMappings" + }, + "directory_endpoint": { + "description": "The endpoint URL generated by Scalekit for synchronizing users and groups from the Directory Provider", + "type": "string", + "examples": [ + "https://yourapp.scalekit.com/api/v1/directoies/dir_123212312/scim/v2" + ] + }, + "directory_provider": { + "description": "Identity provider connected to this directory", + "$ref": "#/components/schemas/directoriesDirectoryProvider", + "examples": [ + "OKTA" + ] + }, + "directory_type": { + "description": "Type of the directory, indicating the protocol or standard used for synchronization", + "$ref": "#/components/schemas/directoriesDirectoryType", + "examples": [ + "SCIM" + ] + }, + "email": { + "description": "Email Id associated with Directory whose access will be used for polling", + "type": "string", + "examples": [ + "john.doe@scalekit.cloud" + ] + }, + "enabled": { + "description": "Indicates whether the directory is currently enabled and actively synchronizing users and groups", + "type": "boolean", + "examples": [ + true + ] + }, + "groups_tracked": { + "description": "It indicates if all groups are tracked or select groups are tracked", + "type": "string", + "examples": [ + "ALL" + ] + }, + "id": { + "description": "Unique identifier of the directory", + "type": "string", + "examples": [ + "dir_121312434123312" + ] + }, + "last_synced_at": { + "description": "Timestamp of the last successful synchronization of users and groups from the Directory Provider", + "type": "string", + "format": "date-time", + "examples": [ + "2024-10-01T00:00:00Z" + ] + }, + "name": { + "description": "Name of the directory, typically representing the connected Directory provider", + "type": "string", + "examples": [ + "Azure AD" + ] + }, + "organization_id": { + "description": "Unique identifier of the organization to which the directory belongs", + "type": "string", + "examples": [ + "org_121312434123312" + ] + }, + "role_assignments": { + "description": "Role assignments associated with the directory, defining group based role assignments", + "$ref": "#/components/schemas/directoriesRoleAssignments" + }, + "secrets": { + "description": "List of secrets used for authenticating and synchronizing with the Directory Provider", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/directoriesSecret" + } + }, + "stats": { + "description": "Statistics and metrics related to the directory, such as synchronization status and error counts", + "$ref": "#/components/schemas/directoriesStats" + }, + "status": { + "description": "Directory Status", + "type": "string", + "examples": [ + "IN_PROGRESS" + ] + }, + "total_groups": { + "description": "Total number of groups in the directory", + "type": "integer", + "format": "int32", + "examples": [ + 10 + ] + }, + "total_users": { + "description": "Total number of users in the directory", + "type": "integer", + "format": "int32", + "examples": [ + 10 + ] + } + } + }, + "directoriesListDirectoriesResponse": { + "type": "object", + "properties": { + "directories": { + "description": "List of directories associated with the organization", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/directoriesDirectory" + } + } + } + }, + "directoriesDirectoryGroup": { + "type": "object", + "properties": { + "display_name": { + "description": "Display Name", + "type": "string", + "examples": [ + "Admins" + ] + }, + "group_detail": { + "description": "Complete Group Details Payload", + "type": "object" + }, + "id": { + "description": "Group ID", + "type": "string", + "examples": [ + "dirgroup_121312434123312" + ] + }, + "total_users": { + "description": "Total Users in the Group", + "type": "integer", + "format": "int32", + "examples": [ + 10 + ] + }, + "updated_at": { + "description": "Updated At", + "type": "string", + "format": "date-time", + "examples": [ + "2024-10-01T00:00:00Z" + ] + } + } + }, + "directoriesListDirectoryGroupsResponse": { + "type": "object", + "properties": { + "groups": { + "description": "List of directory groups retrieved from the specified directory", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/directoriesDirectoryGroup" + } + }, + "next_page_token": { + "description": "Token to retrieve the next page of results. Use this token in the 'page_token' field of the next request", + "type": "string" + }, + "prev_page_token": { + "description": "Token to retrieve the previous page of results. Use this token in the 'page_token' field of the next request", + "type": "string" + }, + "total_size": { + "description": "Total number of groups matching the request criteria, regardless of pagination", + "type": "integer", + "format": "int64" + } + } + }, + "directoriesDirectoryUser": { + "type": "object", + "properties": { + "email": { + "description": "Email", + "type": "string", + "examples": [ + "johndoe" + ] + }, + "emails": { + "description": "Emails", + "type": "array", + "items": { + "type": "string" + } + }, + "family_name": { + "description": "Last Name", + "type": "string", + "examples": [ + "Doe" + ] + }, + "given_name": { + "description": "First Name", + "type": "string", + "examples": [ + "John" + ] + }, + "groups": { + "description": "Groups", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/directoriesDirectoryGroup" + } + }, + "id": { + "description": "User ID", + "type": "string", + "examples": [ + "diruser_121312434123312" + ] + }, + "preferred_username": { + "description": "Preferred Username", + "type": "string", + "examples": [ + "johndoe" + ] + }, + "updated_at": { + "description": "Updated At", + "type": "string", + "format": "date-time", + "examples": [ + "2024-10-01T00:00:00Z" + ] + }, + "user_detail": { + "description": "Complete User Details Payload", + "type": "object" + } + } + }, + "directoriesListDirectoryUsersResponse": { + "type": "object", + "properties": { + "next_page_token": { + "description": "Token for pagination. Use this token in the 'page_token' field of the next request to fetch the subsequent page of users", + "type": "string" + }, + "prev_page_token": { + "description": "Token for pagination. Use this token in the 'page_token' field of the next request to fetch the prior page of users", + "type": "string" + }, + "total_size": { + "description": "Total number of users available in the directory that match the request criteria", + "type": "integer", + "format": "int64" + }, + "users": { + "description": "List of directory users retrieved from the specified directory", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/directoriesDirectoryUser" + } + } + } + }, + "directoriesGetDirectoryResponse": { + "type": "object", + "properties": { + "directory": { + "description": "Detailed information about the requested directory", + "$ref": "#/components/schemas/directoriesDirectory" + } + } + }, + "directoriesToggleDirectoryResponse": { + "type": "object", + "properties": { + "enabled": { + "description": "Specifies the directory's state after the toggle operation. A value of `true` indicates that the directory is enabled and actively synchronizing users and groups. A value of `false` means the directory is disabled, halting synchronization", + "type": "boolean", + "examples": [ + true + ] + }, + "error_message": { + "description": "Contains a human-readable error message if the toggle operation encountered an issue. If the operation was successful, this field will be empty", + "type": "string", + "examples": [ + "The directory is already enabled" + ] + } + } + }, + "domainsListDomainResponse": { + "type": "object", + "properties": { + "domains": { + "description": "Array of domain objects containing all domain details including verification status and configuration.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/domainsDomain" + } + }, + "page_number": { + "description": "Current page number in the pagination sequence.", + "type": "integer", + "format": "int32", + "examples": [ + 1 + ] + }, + "page_size": { + "description": "Number of domains returned in this page.", + "type": "integer", + "format": "int32", + "examples": [ + 1 + ] + } + } + }, + "domainsDomainType": { + "type": "string", + "enum": [ + "ALLOWED_EMAIL_DOMAIN", + "ORGANIZATION_DOMAIN" + ], + "x-enum-varnames": [ + "ORGANIZATION_DOMAIN", + "ALLOWED_EMAIL_DOMAIN" + ] + }, + "v1domainsCreateDomain": { + "type": "object", + "properties": { + "domain": { + "description": "The domain name to be configured. Must be a valid business domain you control. Public and disposable domains (gmail.com, outlook.com, etc.) are automatically blocked for security.", + "type": "string", + "examples": [ + "customerdomain.com" + ] + }, + "domain_type": { + "description": "The domain type.\n- ALLOWED_EMAIL_DOMAIN: trusted domain used to suggest the organization in the organization switcher during sign-in/sign-up.\n- ORGANIZATION_DOMAIN: SSO discovery domain used to route users to the correct SSO provider and enforce SSO.\n", + "$ref": "#/components/schemas/domainsDomainType", + "examples": [ + "ORGANIZATION_DOMAIN" + ] + } + } + }, + "domainsCreateDomainResponse": { + "type": "object", + "properties": { + "domain": { + "description": "The newly created domain object with all configuration details and system-generated identifiers.", + "$ref": "#/components/schemas/domainsDomain" + } + } + }, + "domainsGetDomainResponse": { + "type": "object", + "properties": { + "domain": { + "description": "The requested domain object with complete details including domain type, timestamps and configuration.", + "$ref": "#/components/schemas/domainsDomain" + } + } + }, + "organizationsOrganizationUserManagementSettings": { + "type": "object", + "properties": { + "max_allowed_users": { + "description": "Maximum number of users allowed in the organization. When nil (not set), there feature is not enabled. When explicitly set to zero, it also means no limit. When set to a positive integer, it enforces the maximum user limit.", + "type": "integer", + "format": "int32", + "examples": [ + 100 + ] + } + } + }, + "OrganizationServiceUpsertUserManagementSettingsBody": { + "type": "object", + "properties": { + "settings": { + "description": "The new values for the setting fields to patch.", + "$ref": "#/components/schemas/organizationsOrganizationUserManagementSettings" + } + } + }, + "organizationsUpsertUserManagementSettingsResponse": { + "type": "object", + "properties": { + "settings": { + "description": "The updated setting.", + "$ref": "#/components/schemas/organizationsOrganizationUserManagementSettings" + } + } + }, + "usersListOrganizationUsersResponse": { + "type": "object", + "properties": { + "next_page_token": { + "description": "Opaque token for retrieving the next page of results. Empty if there are no more pages.", + "type": "string", + "examples": [ + "eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0=" + ] + }, + "prev_page_token": { + "description": "Opaque token for retrieving the previous page of results. Empty for the first page.", + "type": "string", + "examples": [ + "eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9" + ] + }, + "total_size": { + "description": "Total number of users matching the request criteria, regardless of pagination.", + "type": "integer", + "format": "int64", + "examples": [ + 1042 + ] + }, + "users": { + "description": "List of user objects for the current page. May contain fewer entries than requested page_size.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/usersUser" + } + } + } + }, + "usersCreateUserProfile": { + "type": "object", + "properties": { + "custom_attributes": { + "description": "Custom attributes for extended user profile data. Keys (3-25 chars), values (1-256 chars).", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "department": "engineering", + "security_clearance": "level2" + } + ] + }, + "family_name": { + "description": "User's family name. Maximum 255 characters.", + "type": "string", + "examples": [ + "Doe" + ] + }, + "gender": { + "description": "User's gender identity.", + "type": "string", + "examples": [ + "male" + ] + }, + "given_name": { + "description": "User's given name. Maximum 255 characters.", + "type": "string", + "examples": [ + "John" + ] + }, + "groups": { + "description": "List of group names the user belongs to. Each group name must be 1-250 characters", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "engineering", + "managers" + ] + ] + }, + "locale": { + "description": "User's localization preference in BCP-47 format. Defaults to organization settings.", + "type": "string", + "examples": [ + "en-US" + ] + }, + "metadata": { + "description": "System-managed key-value pairs for internal tracking. Keys (3-25 chars), values (1-256 chars).", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "account_status": "active", + "signup_source": "mobile_app" + } + ] + }, + "name": { + "description": "Full name in display format. Typically combines first_name and last_name.", + "type": "string", + "examples": [ + "John Michael Doe" + ] + }, + "phone_number": { + "description": "Phone number in E.164 international format. Required for SMS-based authentication.", + "type": "string", + "examples": [ + "+14155552671" + ] + }, + "picture": { + "description": "URL to the user's profile picture or avatar.", + "type": "string", + "examples": [ + "https://example.com/avatar.jpg" + ] + }, + "preferred_username": { + "description": "User's preferred username for display purposes.", + "type": "string", + "examples": [ + "John Michael Doe" + ] + } + } + }, + "usersCreateUser": { + "type": "object", + "properties": { + "email": { + "description": "Primary email address for the user. Must be unique across the environment and valid per RFC 5322.", + "type": "string", + "examples": [ + "user@example.com" + ] + }, + "external_id": { + "description": "Your application's unique identifier for this organization, used to link Scalekit with your system.", + "type": "string", + "examples": [ + "ext_12345a67b89c" + ] + }, + "membership": { + "description": "List of organization memberships. Automatically populated based on group assignments.", + "$ref": "#/components/schemas/v1usersCreateMembership" + }, + "metadata": { + "description": "Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars).", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "department": "engineering", + "location": "nyc-office" + } + ] + }, + "user_profile": { + "description": "User's personal information including name, address, and other profile attributes.", + "$ref": "#/components/schemas/usersCreateUserProfile" + } + } + }, + "usersCreateUserAndMembershipResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/usersUser" + } + } + }, + "usersPermission": { + "type": "object", + "properties": { + "description": { + "description": "Description of what the permission allows", + "type": "string", + "examples": [ + "Allows creating new user accounts" + ] + }, + "id": { + "description": "Unique identifier for the permission", + "type": "string", + "readOnly": true, + "examples": [ + "perm_1234abcd5678efgh" + ] + }, + "name": { + "description": "Unique name identifier for the permission", + "type": "string", + "examples": [ + "users:create" + ] + } + } + }, + "usersListUserPermissionsResponse": { + "type": "object", + "properties": { + "permissions": { + "description": "List of permissions the user has access to", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/usersPermission" + } + } + } + }, + "usersListUserRolesResponse": { + "type": "object", + "properties": { + "roles": { + "description": "List of roles assigned to the user", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/commonsRole" + } + } + } + }, + "usersSearchOrganizationUsersResponse": { + "type": "object", + "properties": { + "next_page_token": { + "description": "Token for retrieving the next page of results. Empty if there are no more pages.", + "type": "string", + "examples": [ + "eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0=" + ] + }, + "prev_page_token": { + "description": "Token for retrieving the previous page of results. Empty if this is the first page.", + "type": "string", + "examples": [ + "eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9" + ] + }, + "total_size": { + "description": "Total number of users matching the request criteria, regardless of pagination.", + "type": "integer", + "format": "int64", + "examples": [ + 1042 + ] + }, + "users": { + "description": "List of matching users.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/usersUser" + } + } + } + }, + "passwordlessResendPasswordlessRequest": { + "type": "object", + "properties": { + "auth_request_id": { + "description": "The authentication request identifier from the original send passwordless email request. Use this to resend the Verification Code (OTP) or Magic Link to the same email address.", + "type": "string", + "examples": [ + "h5Y8kT5RVwaea5WEgW4n-6C-aO_-fuTUW7Vb9-Rh3AcY9qxZqQ" + ] + } + } + }, + "authpasswordlessPasswordlessType": { + "type": "string", + "enum": [ + "OTP", + "LINK", + "LINK_OTP" + ] + }, + "passwordlessSendPasswordlessResponse": { + "type": "object", + "properties": { + "auth_request_id": { + "description": "Unique identifier for this passwordless authentication request. Use this ID to resend emails.", + "type": "string", + "readOnly": true, + "examples": [ + "h5Y8kT5RVwaea5WEgW4n-6C-aO_-fuTUW7Vb9-Rh3AcY9qxZqQ" + ] + }, + "expires_at": { + "description": "Unix timestamp (seconds since epoch) when the passwordless authentication will expire. After this time, the OTP or magic link will no longer be valid.", + "type": "string", + "format": "int64", + "readOnly": true, + "examples": [ + 1748696575 + ] + }, + "expires_in": { + "description": "Number of seconds from now until the passwordless authentication expires. This is a convenience field calculated from the expires_at timestamp.", + "type": "integer", + "format": "int64", + "readOnly": true, + "examples": [ + 300 + ] + }, + "passwordless_type": { + "description": "Type of passwordless authentication that was sent via email. OTP sends a numeric code, LINK sends a clickable magic link, and LINK_OTP provides both options for user convenience.", + "$ref": "#/components/schemas/authpasswordlessPasswordlessType", + "examples": [ + "OTP" + ] + } + } + }, + "passwordlessTemplateType": { + "type": "string", + "enum": [ + "SIGNIN", + "SIGNUP" + ] + }, + "passwordlessSendPasswordlessRequest": { + "type": "object", + "properties": { + "email": { + "description": "Email address where the passwordless authentication credentials will be sent. Must be a valid email format.", + "type": "string", + "examples": [ + "john.doe@example.com" + ] + }, + "expires_in": { + "description": "Time in seconds until the passwordless authentication expires. If not specified, defaults to 300 seconds (5 minutes)", + "type": "integer", + "format": "int64", + "examples": [ + 300 + ] + }, + "magiclink_auth_uri": { + "description": "Your application's callback URL where users will be redirected after clicking the magic link in their email. The link token will be appended as a query parameter as link_token", + "type": "string", + "examples": [ + "https://yourapp.com/auth/passwordless/callback" + ] + }, + "state": { + "description": "Custom state parameter that will be returned unchanged in the verification response. Use this to maintain application state between the authentication request and callback, such as the intended destination after login", + "type": "string", + "examples": [ + "d62ivasry29lso" + ] + }, + "template": { + "description": "Specifies the authentication intent for the passwordless request. Use SIGNIN for existing users or SIGNUP for new user registration. This affects the email template and user experience flow.", + "$ref": "#/components/schemas/passwordlessTemplateType", + "examples": [ + "SIGNIN" + ] + }, + "template_variables": { + "description": "A set of key-value pairs to personalize the email template.\n\n* You may include up to 30 key-value pairs.\n* The following variable names are reserved by the system and cannot be supplied: `otp`, `expiry_time_relative`, `link`, `expire_time`, `expiry_time`.\n* Every variable referenced in your email template must be included as a key-value pair.\n\nUse these variables to insert custom information, such as a team name, URL or the user's employee ID. All variables are interpolated before the email is sent, regardless of the email provider.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "custom_variable_key": "custom_variable_value" + } + ] + } + } + }, + "passwordlessVerifyPasswordLessRequest": { + "type": "object", + "properties": { + "auth_request_id": { + "description": "The authentication request identifier returned from the send passwordless email endpoint. Required when verifying OTP codes to link the verification with the original request.", + "type": "string", + "examples": [ + "h5Y8kT5RVwaea5WEgW4n-6C-aO_-fuTUW7Vb9-Rh3AcY9qxZqQ" + ] + }, + "code": { + "description": "The Verification Code (OTP) received via email. This is typically a 6-digit numeric code that users enter manually to verify their identity.", + "type": "string", + "examples": [ + "123456" + ] + }, + "link_token": { + "description": "The unique token from the magic link URL received via email. Extract this token when users click the magic link and are redirected to your application to later verify the user.", + "type": "string", + "examples": [ + "afe9d61c-d80d-4020-a8ee-61765ab71cb3" + ] + } + } + }, + "passwordlessVerifyPasswordLessResponse": { + "type": "object", + "properties": { + "email": { + "description": "Email address of the successfully authenticated user. This confirms which email account was verified through the passwordless flow.", + "type": "string", + "readOnly": true, + "examples": [ + "john.doe@example.com" + ] + }, + "passwordless_type": { + "description": "The type of passwordless authentication that was successfully verified, confirming which method the user completed.", + "$ref": "#/components/schemas/authpasswordlessPasswordlessType", + "examples": [ + "OTP" + ] + }, + "state": { + "description": "The custom state parameter that was provided in the original authentication request, returned unchanged. Use this to restore your application's context after authentication.", + "type": "string", + "readOnly": true, + "examples": [ + "kdt7yiag28t341fr1" + ] + }, + "template": { + "description": "Specifies which email template to choose. For User Signin choose SIGNIN and for User Signup use SIGNUP", + "$ref": "#/components/schemas/passwordlessTemplateType", + "examples": [ + "SIGNIN" + ] + } + } + }, + "rolesPermission": { + "type": "object", + "title": "Permission Entity", + "properties": { + "create_time": { + "type": "string", + "format": "date-time" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "is_scalekit_permission": { + "description": "Indicates whether this permission is predefined by Scalekit", + "type": "boolean", + "examples": [ + true + ] + }, + "name": { + "type": "string" + }, + "update_time": { + "type": "string", + "format": "date-time" + } + } + }, + "rolesListPermissionsResponse": { + "type": "object", + "properties": { + "next_page_token": { + "description": "Token to retrieve next page of results", + "type": "string", + "examples": [ + "token_def456" + ] + }, + "permissions": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/rolesPermission" + } + }, + "prev_page_token": { + "description": "Token to retrieve previous page of results", + "type": "string", + "examples": [ + "token_def456" + ] + }, + "total_size": { + "description": "Total number of permissions available", + "type": "integer", + "format": "int64", + "examples": [ + 150 + ] + } + } + }, + "v1rolesCreatePermission": { + "type": "object", + "properties": { + "description": { + "description": "Description of the permission", + "type": "string", + "examples": [ + "Allows user to read documents from the system" + ] + }, + "name": { + "description": "Unique name/ID of the permission", + "type": "string", + "examples": [ + "read:documents" + ] + } + } + }, + "rolesCreatePermissionResponse": { + "type": "object", + "properties": { + "permission": { + "$ref": "#/components/schemas/rolesPermission" + } + } + }, + "rolesGetPermissionResponse": { + "type": "object", + "properties": { + "permission": { + "$ref": "#/components/schemas/rolesPermission" + } + } + }, + "rolesUpdatePermissionResponse": { + "type": "object", + "properties": { + "permission": { + "$ref": "#/components/schemas/rolesPermission" + } + } + }, + "rolesListRolesResponse": { + "type": "object", + "properties": { + "roles": { + "description": "List of all roles in the environment with their metadata and optionally their permissions.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/v1rolesRole" + }, + "examples": [ + [ + { + "display_name": "Administrator", + "id": "role_1234abcd5678efgh", + "name": "admin" + }, + { + "display_name": "Viewer", + "id": "role_9876zyxw5432vuts", + "name": "viewer" + } + ] + ] + } + } + }, + "v1rolesCreateRole": { + "type": "object", + "properties": { + "description": { + "description": "Detailed description of the role's purpose, capabilities, and intended use cases. Maximum 2000 characters.", + "type": "string", + "examples": [ + "Can create, edit, and publish content but cannot delete content or manage user accounts" + ] + }, + "display_name": { + "description": "Human-readable display name for the role. Used in user interfaces, reports, and user-facing communications.", + "type": "string", + "examples": [ + "Content Editor" + ] + }, + "extends": { + "description": "Name of the base role that this role extends. Enables hierarchical role inheritance where this role inherits all permissions from the base role.", + "type": "string", + "examples": [ + "viewer" + ] + }, + "name": { + "description": "Unique name identifier for the role. Must be alphanumeric with underscores, 1-64 characters. This name is used in API calls and cannot be changed after creation.", + "type": "string", + "examples": [ + "content_editor" + ] + }, + "permissions": { + "description": "List of permission names to assign to this role. Permissions must exist in the current environment. Maximum 100 permissions per role.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "read:content", + "write:content", + "publish:content" + ] + ] + } + } + }, + "rolesCreateRoleResponse": { + "type": "object", + "properties": { + "role": { + "description": "The created role object with system-generated ID and all configuration details.", + "$ref": "#/components/schemas/v1rolesRole", + "examples": [ + { + "description": "Can edit content", + "display_name": "Content Editor", + "id": "role_1234abcd5678efgh", + "name": "content_editor" + } + ] + } + } + }, + "rolesUpdateDefaultRole": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "description": "Unique name of the role", + "type": "string", + "examples": [ + "creator" + ] + } + } + }, + "rolesUpdateDefaultRolesRequest": { + "type": "object", + "properties": { + "default_creator": { + "description": "Default creator role (deprecated - use default_creator_role field instead)", + "$ref": "#/components/schemas/rolesUpdateDefaultRole", + "examples": [ + { + "description": "Role for creating resources", + "display_name": "Creator Role", + "id": "role_1234567890", + "name": "creator" + } + ] + }, + "default_creator_role": { + "description": "Name of the role to set as the default creator role. This role will be automatically assigned to users who create new resources in the environment. Must be a valid role name that exists in the environment.", + "type": "string", + "examples": [ + "creator" + ] + }, + "default_member": { + "description": "Default member role (deprecated - use default_member_role field instead)", + "$ref": "#/components/schemas/rolesUpdateDefaultRole", + "examples": [ + { + "description": "Role for regular members", + "display_name": "Member Role", + "id": "role_0987654321", + "name": "member" + } + ] + }, + "default_member_role": { + "description": "Name of the role to set as the default member role. This role will be automatically assigned to new users when they join the environment. Must be a valid role name that exists in the environment.", + "type": "string", + "examples": [ + "member" + ] + } + } + }, + "rolesUpdateDefaultRolesResponse": { + "type": "object", + "properties": { + "default_creator": { + "description": "The role that is now set as the default creator role for the environment. Contains complete role information including permissions and metadata.", + "$ref": "#/components/schemas/v1rolesRole", + "examples": [ + { + "description": "Role for creating resources", + "display_name": "Creator Role", + "id": "role_1234567890", + "name": "creator" + } + ] + }, + "default_member": { + "description": "The role that is now set as the default member role for the environment. Contains complete role information including permissions and metadata.", + "$ref": "#/components/schemas/v1rolesRole", + "examples": [ + { + "description": "Role for regular members", + "display_name": "Member Role", + "id": "role_0987654321", + "name": "member" + } + ] + } + } + }, + "rolesGetRoleResponse": { + "type": "object", + "properties": { + "role": { + "description": "The complete role object with all metadata, permissions, and inheritance details.", + "$ref": "#/components/schemas/v1rolesRole", + "examples": [ + { + "dependent_roles_count": 2, + "display_name": "Content Editor", + "id": "role_1234abcd5678efgh", + "name": "content_editor", + "permissions": [ + { + "name": "read:content" + } + ] + } + ] + } + } + }, + "rolesUpdateRoleResponse": { + "type": "object", + "properties": { + "role": { + "description": "The updated role object with all current configuration details.", + "$ref": "#/components/schemas/v1rolesRole", + "examples": [ + { + "description": "Can edit and approve content", + "display_name": "Senior Editor", + "id": "role_1234abcd5678efgh", + "name": "content_editor" + } + ] + } + } + }, + "rolesListDependentRolesResponse": { + "type": "object", + "properties": { + "roles": { + "description": "List of dependent roles", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/v1rolesRole" + } + } + } + }, + "rolesListRolePermissionsResponse": { + "type": "object", + "properties": { + "permissions": { + "description": "List of permissions directly assigned to the role", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/rolesPermission" + } + } + } + }, + "RolesServiceAddPermissionsToRoleBody": { + "type": "object", + "properties": { + "permission_names": { + "description": "List of permission names to add to the role", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "rolesAddPermissionsToRoleResponse": { + "type": "object", + "properties": { + "permissions": { + "description": "List of all permissions belonging to the role after addition", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/rolesPermission" + } + } + } + }, + "rolesListEffectiveRolePermissionsResponse": { + "type": "object", + "properties": { + "permissions": { + "description": "List of all effective permissions including those inherited from base roles", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/rolesPermission" + } + } + } + }, + "rolesGetRoleUsersCountResponse": { + "type": "object", + "properties": { + "count": { + "description": "Number of users associated with the role", + "type": "string", + "format": "int64", + "examples": [ + 10 + ] + } + } + }, + "sessionsAuthenticatedClients": { + "description": "AuthenticatedClients represents an authenticated client in a session along with its organization context.", + "type": "object", + "properties": { + "client_id": { + "description": "Unique identifier of the authenticated client application.", + "type": "string", + "examples": [ + "skc_1234567890" + ] + }, + "organization_id": { + "description": "Active or last active Organization ID associated with the authenticated client.", + "type": "string", + "examples": [ + "org_1234567890" + ] + } + } + }, + "v1sessionsLocation": { + "type": "object", + "properties": { + "city": { + "description": "City name where the session originated based on IP geolocation. Approximate location derived from IP address.", + "type": "string", + "examples": [ + "San Francisco" + ] + }, + "latitude": { + "description": "Latitude coordinate of the estimated location. Decimal format (e.g., '37.7749'). Note: Represents IP geolocation center and may not be precise.", + "type": "string", + "examples": [ + "37.7749" + ] + }, + "longitude": { + "description": "Longitude coordinate of the estimated location. Decimal format (e.g., '-122.4194'). Note: Represents IP geolocation center and may not be precise.", + "type": "string", + "examples": [ + "-122.4194" + ] + }, + "region": { + "description": "Geographic region name derived from IP geolocation. Represents the country-level location (e.g., 'United States', 'France').", + "type": "string", + "examples": [ + "United States" + ] + }, + "region_subdivision": { + "description": "Regional subdivision code or name (e.g., state abbreviation for US, province for Canada). Two-letter ISO format when applicable.", + "type": "string", + "examples": [ + "CA" + ] + } + } + }, + "sessionsDeviceDetails": { + "type": "object", + "properties": { + "browser": { + "description": "Browser name and family extracted from the user agent. Examples: Chrome, Safari, Firefox, Edge, Mobile Safari.", + "type": "string", + "examples": [ + "Chrome" + ] + }, + "browser_version": { + "description": "Version of the browser application. Represents the specific release version of the browser being used.", + "type": "string", + "examples": [ + "120.0.0.0" + ] + }, + "device_type": { + "description": "Categorized device type classification. Possible values: 'desktop' (traditional computers), 'mobile' (smartphones and small tablets), 'tablet' (large tablets), 'other'. Useful for displaying session information by device category.", + "type": "string", + "examples": [ + "desktop" + ] + }, + "ip": { + "description": "IP address of the device that initiated the session. This is the public-facing IP address used to connect to the application. Useful for security audits and geographic distribution analysis.", + "type": "string", + "examples": [ + "192.0.2.1" + ] + }, + "location": { + "description": "Geographic location information derived from IP address geolocation. Includes country, region, city, and coordinates. Note: Based on IP location data and may not represent the user's exact physical location.", + "$ref": "#/components/schemas/v1sessionsLocation" + }, + "os": { + "description": "Operating system name extracted from the user agent and device headers. Examples: macOS, Windows, Linux, iOS, Android.", + "type": "string", + "examples": [ + "macOS" + ] + }, + "os_version": { + "description": "Version of the operating system. Represents the specific OS release the device is running.", + "type": "string", + "examples": [ + "14.2" + ] + }, + "user_agent": { + "description": "Complete HTTP User-Agent header string from the client request. Contains browser type, version, and operating system information. Used for detailed device fingerprinting and user agent analysis.", + "type": "string", + "examples": [ + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" + ] + } + } + }, + "sessionsSessionDetails": { + "type": "object", + "properties": { + "absolute_expires_at": { + "description": "Hard expiration timestamp for the session regardless of user activity. The session will be forcibly terminated at this time. This represents the maximum session lifetime from creation.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-22T10:30:00Z" + ] + }, + "authenticated_clients": { + "description": "Details of the authenticated clients for this session: client ID and organization context.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/sessionsAuthenticatedClients" + } + }, + "authenticated_organizations": { + "description": "List of organization IDs that have been authenticated for this user within the current session. Contains all organizations where the user has successfully completed SSO or authentication.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "org_123", + "org_456" + ] + ] + }, + "created_at": { + "description": "Timestamp indicating when the session was created. This is set once at session creation and remains constant throughout the session lifetime.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T10:30:00Z" + ] + }, + "device": { + "description": "Complete device metadata associated with this session including browser, operating system, device type, and geographic location based on IP address.", + "$ref": "#/components/schemas/sessionsDeviceDetails" + }, + "expired_at": { + "description": "Timestamp when the session was terminated. Null if the session is still active. Set when the session expires due to reaching idle_expires_at or absolute_expires_at timeout, or when administratively revoked. Not set for user-initiated logout (see logout_at instead).", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T12:00:00Z" + ] + }, + "idle_expires_at": { + "description": "Projected expiration timestamp if the session remains idle without user activity. This timestamp is recalculated with each user activity. Session will be automatically terminated at this time if no activity occurs.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T11:30:00Z" + ] + }, + "last_active_at": { + "description": "Timestamp of the most recent user activity detected in this session. Updated on each API request or user interaction. Used to determine if a session has exceeded the idle timeout threshold.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T10:55:30Z" + ] + }, + "logout_at": { + "description": "Timestamp when the user explicitly logged out from the session. Null if the user has not logged out. When set, indicates the session ended due to explicit user logout rather than timeout.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T14:00:00Z" + ] + }, + "organization_id": { + "description": "Organization ID for the user's most recently active organization within this session. This represents the primary organization context for the current session.", + "type": "string", + "examples": [ + "org_1234567890123456" + ] + }, + "session_id": { + "description": "Unique identifier for the session. System-generated read-only field used to reference this session.", + "type": "string", + "examples": [ + "ses_1234567890123456" + ] + }, + "status": { + "description": "Current operational status of the session. Possible values: 'active' (session is valid and requests are allowed), 'expired' (session terminated due to idle or absolute timeout), 'revoked' (session was administratively revoked), 'logout' (user explicitly logged out). Use this to determine if the session can be used for new requests.", + "type": "string", + "examples": [ + "active" + ] + }, + "updated_at": { + "description": "Timestamp indicating when the session was last updated. Updated whenever session state changes such as organization context changes or metadata updates.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T10:45:00Z" + ] + }, + "user_id": { + "description": "Unique identifier for the user who owns and is authenticated within this session.", + "type": "string", + "examples": [ + "usr_1234567890123456" + ] + } + } + }, + "sessionsRevokedSessionDetails": { + "type": "object", + "properties": { + "absolute_expires_at": { + "description": "The absolute expiration timestamp that was configured for this session before revocation. Represents the hard deadline regardless of activity.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-22T10:30:00Z" + ] + }, + "created_at": { + "description": "Timestamp indicating when the session was originally created before revocation.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T10:30:00Z" + ] + }, + "expired_at": { + "description": "Timestamp when the session was actually terminated. Set to the revocation time when the session is revoked.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T12:00:00Z" + ] + }, + "idle_expires_at": { + "description": "The idle expiration timestamp that was configured for this session before revocation. Represents when the session would have expired due to inactivity.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T11:30:00Z" + ] + }, + "last_active_at": { + "description": "Timestamp of the last recorded user activity in this session before revocation. Helps identify inactive sessions that were revoked.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T10:55:30Z" + ] + }, + "logout_at": { + "description": "Timestamp when the user explicitly logged out (if applicable). Null if the session was revoked without prior logout.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T14:00:00Z" + ] + }, + "session_id": { + "description": "Unique identifier for the revoked session. System-generated read-only field.", + "type": "string", + "examples": [ + "ses_1234567890123456" + ] + }, + "status": { + "description": "Status of the session after revocation. Always 'revoked' since only active sessions can be revoked. Sessions that were already expired or logged out are not included in the revocation response.", + "type": "string", + "examples": [ + "revoked" + ] + }, + "updated_at": { + "description": "Timestamp indicating when the session was last modified before revocation.", + "type": "string", + "format": "date-time", + "examples": [ + "2025-01-15T10:45:00Z" + ] + }, + "user_id": { + "description": "Unique identifier for the user who owned this session.", + "type": "string", + "examples": [ + "usr_1234567890123456" + ] + } + } + }, + "sessionsRevokeSessionResponse": { + "type": "object", + "properties": { + "revoked_session": { + "description": "Details of the revoked session including session ID, user ID, creation and revocation timestamps, and final device information.", + "$ref": "#/components/schemas/sessionsRevokedSessionDetails" + } + } + }, + "usersListUsersResponse": { + "type": "object", + "properties": { + "next_page_token": { + "description": "Token for retrieving the next page of results. Empty if there are no more pages.", + "type": "string", + "examples": [ + "eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0=" + ] + }, + "prev_page_token": { + "description": "Token for retrieving the previous page of results. Empty if this is the first page.", + "type": "string", + "examples": [ + "eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9" + ] + }, + "total_size": { + "description": "Total number of users matching the request criteria, regardless of pagination.", + "type": "integer", + "format": "int64", + "examples": [ + 1042 + ] + }, + "users": { + "description": "List of users.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/usersUser" + } + } + } + }, + "usersGetUserResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/usersUser" + } + } + }, + "usersUpdateUserProfile": { + "type": "object", + "properties": { + "custom_attributes": { + "description": "Updates custom attributes for extended user profile data and application-specific information. Use this field to store business-specific user data like department, job title, security clearances, project assignments, or any other organizational attributes your application requires. Unlike system metadata, these attributes are typically managed by administrators or applications and are visible to end users. Keys must be 3-25 characters, values must be 1-256 characters, with a maximum of 20 key-value pairs.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "department": "engineering", + "security_clearance": "level2" + } + ] + }, + "family_name": { + "description": "Updates the user's family name (last name or surname). Use this field to modify how the user's last name appears throughout the system. Maximum 255 characters allowed.", + "type": "string", + "examples": [ + "Doe" + ] + }, + "first_name": { + "description": "[DEPRECATED] Use given_name instead. User's given name. Maximum 200 characters.", + "type": "string", + "examples": [ + "John" + ] + }, + "gender": { + "description": "Updates the user's gender identity information. Use this field to store the user's gender identity for personalization, compliance, or reporting purposes. This field supports any string value to accommodate diverse gender identities and should be handled with appropriate privacy considerations according to your organization's policies.", + "type": "string", + "examples": [ + "male" + ] + }, + "given_name": { + "description": "Updates the user's given name (first name). Use this field to modify how the user's first name appears in the system and user interfaces. Maximum 255 characters allowed.", + "type": "string", + "examples": [ + "John" + ] + }, + "groups": { + "description": "Updates the list of group names the user belongs to within the organization. Use this field to manage the user's group memberships for role-based access control, team assignments, or organizational structure. Groups are typically used for permission management and collaborative access. Each group name must be unique within the list, 1-250 characters long, with a maximum of 50 groups per user.", + "type": "array", + "items": { + "type": "string" + }, + "examples": [ + [ + "engineering", + "managers" + ] + ] + }, + "last_name": { + "description": "[DEPRECATED] Use family_name instead. User's family name. Maximum 200 characters.", + "type": "string", + "examples": [ + "Doe" + ] + }, + "locale": { + "description": "Updates the user's preferred language and region settings using BCP-47 format codes. Use this field to customize the user's experience with localized content, date formats, number formatting, and UI language. When not specified, the user inherits the organization's default locale settings. Common values include `en-US`, `en-GB`, `fr-FR`, `de-DE`, and `es-ES`.", + "type": "string", + "examples": [ + "en-US" + ] + }, + "metadata": { + "description": "Updates system-managed key-value pairs for internal tracking and operational data. Use this field to store system-generated metadata like account status, signup source, last activity tracking, or integration-specific identifiers. These fields are typically managed by automated processes rather than direct user input. Keys must be 3-25 characters, values must be 1-256 characters, with a maximum of 20 key-value pairs.", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "account_status": "active", + "signup_source": "mobile_app" + } + ] + }, + "name": { + "description": "Updates the user's complete display name. Use this field when you want to set the full name as a single string rather than using separate given and family names. This name appears in user interfaces, reports, and anywhere a formatted display name is needed.", + "type": "string", + "examples": [ + "John Doe" + ] + }, + "phone_number": { + "description": "Updates the user's phone number in E.164 international format. Use this field to enable SMS-based authentication methods, two-factor authentication, or phone-based account recovery. The phone number must include the country code and be formatted according to E.164 standards (e.g., `+1` for US numbers). This field is required when enabling SMS authentication features.", + "type": "string", + "examples": [ + "+14155552671" + ] + }, + "picture": { + "description": "Updates the URL to the user's profile picture or avatar image. Use this field to set or change the user's profile photo that appears in user interfaces, directory listings, and collaborative features. The URL should point to a publicly accessible image file. Supported formats typically include JPEG, PNG, and GIF. Maximum URL length is 2048 characters.", + "type": "string", + "examples": [ + "https://example.com/avatar.jpg" + ] + }, + "preferred_username": { + "description": "Updates the user's preferred username for display and identification purposes. Use this field to set a custom username that the user prefers to be known by, which may differ from their email or formal name. This username appears in user interfaces, mentions, and informal communications. Maximum 512 characters allowed.", + "type": "string", + "examples": [ + "John Michael Doe" + ] + } + } + }, + "v1usersUpdateUser": { + "type": "object", + "properties": { + "external_id": { + "description": "Your application's unique identifier for this organization, used to link Scalekit with your system.", + "type": "string", + "examples": [ + "ext_12345a67b89c" + ] + }, + "metadata": { + "description": "Custom key-value pairs for storing additional user context. Keys (3-25 chars), values (1-256 chars).", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "examples": [ + { + "department": "engineering", + "location": "nyc-office" + } + ] + }, + "user_profile": { + "description": "User's personal information including name, address, and other profile attributes.", + "$ref": "#/components/schemas/usersUpdateUserProfile" + } + } + }, + "usersUpdateUserResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/usersUser" + } + } + }, + "sessionsUserSessionDetails": { + "type": "object", + "properties": { + "next_page_token": { + "description": "Pagination token for retrieving the next page of results. Empty string if there are no more pages (you have reached the final page of results).", + "type": "string", + "examples": [ + "eyJwYWdlIjogMiwgImxhc3RfaWQiOiAic2VzXzEyMzQ1In0=" + ] + }, + "prev_page_token": { + "description": "Pagination token for retrieving the previous page of results. Empty string for the first page. Use this to navigate backward through result pages.", + "type": "string", + "examples": [ + "eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInNlc183OTAxIn0=" + ] + }, + "sessions": { + "description": "Array of session objects for the requested user. May contain fewer entries than the requested page_size when reaching the final page of results.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/sessionsSessionDetails" + } + }, + "total_size": { + "description": "Total number of sessions matching the applied filter criteria, regardless of pagination. This represents the complete result set size before pagination is applied.", + "type": "integer", + "format": "int64", + "examples": [ + 42 + ] + } + } + }, + "sessionsRevokeAllUserSessionsResponse": { + "type": "object", + "properties": { + "revoked_sessions": { + "description": "List of all sessions that were revoked, including detailed information for each revoked session with IDs, timestamps, and device details.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/sessionsRevokedSessionDetails" + } + }, + "total_revoked": { + "description": "Total count of active sessions that were revoked. Useful for confirmation and audit logging.", + "type": "integer", + "format": "int64", + "examples": [ + 5 + ] + } + } + }, + "usersSearchUsersResponse": { + "type": "object", + "properties": { + "next_page_token": { + "description": "Token for retrieving the next page of results. Empty if there are no more pages.", + "type": "string", + "examples": [ + "eyJwYWdlIjogMiwgImxhc3RfaWQiOiAidXNyXzEyMzQ1In0=" + ] + }, + "prev_page_token": { + "description": "Token for retrieving the previous page of results. Empty if this is the first page.", + "type": "string", + "examples": [ + "eyJwYWdlIjogMCwgImZpcnN0X2lkIjogInVzcl85ODc2NSJ9" + ] + }, + "total_size": { + "description": "Total number of users matching the request criteria, regardless of pagination.", + "type": "integer", + "format": "int64", + "examples": [ + 1042 + ] + }, + "users": { + "description": "List of matching users.", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/usersUser" + } + } + } + }, + "webauthnAllAcceptedCredentialsOptions": { + "type": "object", + "properties": { + "all_accepted_credential_ids": { + "description": "List of credential IDs the user can authenticate with", + "type": "array", + "items": { + "type": "string" + } + }, + "rp_id": { + "description": "Relying Party ID for credential operations", + "type": "string", + "examples": [ + "example.com" + ] + }, + "user_id": { + "description": "User ID for credential verification", + "type": "string", + "examples": [ + "user_xyz789" + ] + } + } + }, + "WebAuthnCredentialAuthenticator": { + "type": "object", + "properties": { + "aaguid": { + "description": "Authenticator Attestation GUID (AAGUID) identifying the device model", + "type": "string" + }, + "attachment": { + "description": "Attachment type: \"platform\" (built-in) or \"cross-platform\"", + "type": "string", + "examples": [ + "platform" + ] + }, + "icon_dark": { + "description": "Icon URL for dark theme display", + "type": "string" + }, + "icon_light": { + "description": "Icon URL for light theme display", + "type": "string" + }, + "name": { + "description": "Human-readable name of the authenticator model", + "type": "string", + "examples": [ + "Apple Touch ID" + ] + } + } + }, + "WebAuthnCredentialAuthenticatorFlags": { + "type": "object", + "properties": { + "backup_eligible": { + "description": "Whether this credential can be backed up to another device", + "type": "boolean" + }, + "backup_state": { + "description": "Whether this credential was synced or backed up", + "type": "boolean" + }, + "user_present": { + "description": "Whether the user was present during authentication", + "type": "boolean" + }, + "user_verified": { + "description": "Whether the user was verified (e.g., fingerprint, PIN)", + "type": "boolean" + } + } + }, + "WebAuthnCredentialClientInfo": { + "type": "object", + "properties": { + "city": { + "description": "City name", + "type": "string", + "examples": [ + "San Francisco" + ] + }, + "ip": { + "description": "IP address from which credential was registered", + "type": "string", + "examples": [ + "192.0.2.1" + ] + }, + "region": { + "description": "Geographic region (e.g., \"US\")", + "type": "string", + "examples": [ + "US" + ] + }, + "region_subdivision": { + "description": "Regional subdivision (e.g., \"CA\")", + "type": "string", + "examples": [ + "CA" + ] + } + } + }, + "WebAuthnCredentialUserAgent": { + "type": "object", + "properties": { + "browser": { + "description": "Browser name (e.g., \"Chrome\", \"Safari\")", + "type": "string", + "examples": [ + "Chrome" + ] + }, + "browser_version": { + "description": "Browser version number", + "type": "string", + "examples": [ + "120.0.6099.129" + ] + }, + "device_model": { + "description": "Device model if available", + "type": "string", + "examples": [ + "iPhone15,2" + ] + }, + "device_type": { + "description": "Device type: \"desktop\", \"mobile\", or \"tablet\"", + "type": "string", + "examples": [ + "mobile" + ] + }, + "os": { + "description": "Operating system name (e.g., \"Windows\", \"iOS\")", + "type": "string", + "examples": [ + "macOS" + ] + }, + "os_version": { + "description": "Operating system version", + "type": "string", + "examples": [ + "14.2" + ] + }, + "raw": { + "description": "Raw user agent string from the browser", + "type": "string" + }, + "url": { + "description": "Parsed user agent URL reference", + "type": "string" + } + } + }, + "webauthnWebAuthnCredential": { + "type": "object", + "properties": { + "attestation_type": { + "description": "Type of attestation: \"none\", \"indirect\", or \"direct\"", + "type": "string", + "examples": [ + "direct" + ] + }, + "authenticator": { + "description": "Authenticator information including model and name", + "$ref": "#/components/schemas/WebAuthnCredentialAuthenticator" + }, + "authenticator_flags": { + "description": "Flags indicating authenticator capabilities", + "$ref": "#/components/schemas/WebAuthnCredentialAuthenticatorFlags" + }, + "client_info": { + "description": "Geographic and network information from registration", + "$ref": "#/components/schemas/WebAuthnCredentialClientInfo" + }, + "created_at": { + "description": "Timestamp when the credential was created", + "type": "string", + "format": "date-time", + "examples": [ + "2025-02-15T06:23:44.560000Z" + ] + }, + "credential_id": { + "description": "The actual credential ID bytes from the authenticator", + "type": "string", + "contentEncoding": "base64" + }, + "display_name": { + "description": "Optional user-friendly name for this passkey", + "type": "string", + "examples": [ + "My Yubikey" + ] + }, + "id": { + "description": "Credential unique identifier", + "type": "string", + "examples": [ + "cred_abc123" + ] + }, + "transports": { + "description": "Supported transports for this credential", + "type": "array", + "items": { + "type": "string" + } + }, + "updated_at": { + "description": "Timestamp of last update", + "type": "string", + "format": "date-time", + "examples": [ + "2025-02-15T06:23:44.560000Z" + ] + }, + "user_agent": { + "description": "Browser and device information from registration", + "$ref": "#/components/schemas/WebAuthnCredentialUserAgent" + }, + "user_id": { + "description": "User ID this credential belongs to", + "type": "string", + "examples": [ + "user_xyz789" + ] + } + } + }, + "webauthnListCredentialsResponse": { + "type": "object", + "properties": { + "all_accepted_credentials_options": { + "description": "Options including RP ID and all accepted credential IDs for authentication", + "$ref": "#/components/schemas/webauthnAllAcceptedCredentialsOptions" + }, + "credentials": { + "description": "All passkeys registered for the user", + "type": "array", + "items": { + "type": "object", + "$ref": "#/components/schemas/webauthnWebAuthnCredential" + } + } + } + }, + "webauthnUnknownCredentialOptions": { + "type": "object", + "properties": { + "credential_id": { + "description": "The deleted credential ID", + "type": "string", + "examples": [ + "cred_abc123" + ] + }, + "rp_id": { + "description": "The RP ID for this credential", + "type": "string", + "examples": [ + "example.com" + ] + } + } + }, + "webauthnDeleteCredentialResponse": { + "type": "object", + "properties": { + "success": { + "description": "Whether the credential was successfully deleted", + "type": "boolean", + "examples": [ + true + ] + }, + "unknown_credential_options": { + "description": "Options for handling unknown credentials in client applications", + "$ref": "#/components/schemas/webauthnUnknownCredentialOptions" + } + } + }, + "WebAuthnServiceUpdateCredentialBody": { + "type": "object", + "properties": { + "display_name": { + "description": "Human-friendly name for this credential (1-120 characters)", + "type": "string", + "examples": [ + "My iPhone 15 Pro" + ] + } + } + }, + "webauthnUpdateCredentialResponse": { + "type": "object", + "properties": { + "credential": { + "description": "The updated credential with new display name", + "$ref": "#/components/schemas/webauthnWebAuthnCredential" + } + } + }, + "ScalekitEvent": { + "type": "object", + "required": [ + "spec_version", + "id", + "type", + "occurred_at", + "environment_id", + "object" + ], + "properties": { + "spec_version": { + "type": "string", + "example": "1", + "description": "The webhook specification version", + "pattern": "^[0-9]+$" + }, + "id": { + "type": "string", + "pattern": "^evt_", + "example": "evt_1234567890abcdef", + "description": "Unique identifier for the webhook event (must be prefixed with \"evt_\")", + "minLength": 1, + "maxLength": 32 + }, + "type": { + "type": "string", + "example": "organization.created", + "description": "The event type", + "enum": [ + "organization.created", + "organization.updated", + "organization.deleted", + "organization.sso_created", + "organization.sso_deleted", + "organization.sso_enabled", + "organization.sso_disabled", + "user.signup", + "user.login", + "user.logout", + "user.organization_invitation", + "user.organization_membership_created", + "user.organization_membership_updated", + "user.organization_membership_deleted", + "organization.directory.user_created", + "organization.directory.user_updated", + "organization.directory.user_deleted", + "organization.directory.group_created", + "organization.directory.group_updated", + "organization.directory.group_deleted", + "organization.directory_enabled", + "organization.directory_disabled", + "role.created", + "role.updated", + "role.deleted", + "permission.created", + "permission.updated", + "permission.deleted" + ] + }, + "occurred_at": { + "type": "string", + "format": "date-time", + "description": "When the event occurred (ISO 8601 format)", + "example": "2024-01-01T00:00:00Z" + }, + "environment_id": { + "type": "string", + "pattern": "^env_", + "example": "env_1234567890abcdef", + "description": "The environment ID where the event occurred", + "minLength": 1, + "maxLength": 32 + }, + "organization_id": { + "type": "string", + "pattern": "^org_", + "example": "org_1234567890abcdef", + "description": "The organization ID (if applicable)", + "minLength": 1, + "maxLength": 32 + }, + "object": { + "type": "string", + "description": "The type of object that triggered the webhook", + "enum": [ + "Organization", + "Connection", + "Role", + "Directory", + "DirectoryUser", + "DirectoryGroup", + "Permission", + "OrgMembership", + "User" + ], + "example": "Organization" + }, + "data": { + "type": "object", + "description": "The event payload (structure varies by event type)", + "additionalProperties": true, + "example": { + "id": "org_1234567890abcdef", + "name": "Example Organization", + "created_at": "2024-01-01T00:00:00Z" + } + }, + "display_name": { + "type": "string", + "description": "Human-readable display name for the event", + "example": "Organization Created", + "minLength": 1, + "maxLength": 200 + } + } + } + } + }, + "x-scalar-environments": { + "production": { + "variables": { + "SCALEKIT_ENVIRONMENT_URL": { + "default": "https://$SCALEKIT_ENVIRONMENT_URL", + "description": "yourapp.scalekit.com" + } + } + }, + "staging": { + "variables": { + "SCALEKIT_ENVIRONMENT_URL": { + "default": "https://$SCALEKIT_ENVIRONMENT_URL", + "description": "yourapp.scalekit.dev" + } + } + } + }, + "x-scalar-active-environment": "staging" +} \ No newline at end of file diff --git a/public/d2/docs/cookbooks/litellm-agentkit-inbox-triage-0.svg b/public/d2/docs/cookbooks/litellm-agentkit-inbox-triage-0.svg index afa63f056..abffc50ef 100644 --- a/public/d2/docs/cookbooks/litellm-agentkit-inbox-triage-0.svg +++ b/public/d2/docs/cookbooks/litellm-agentkit-inbox-triage-0.svg @@ -1,4 +1,4 @@ - + .d2-24141272 .fill-N1{fill:#0A0F25;} + .d2-24141272 .fill-N2{fill:#676C7E;} + .d2-24141272 .fill-N3{fill:#9499AB;} + .d2-24141272 .fill-N4{fill:#CFD2DD;} + .d2-24141272 .fill-N5{fill:#DEE1EB;} + .d2-24141272 .fill-N6{fill:#EEF1F8;} + .d2-24141272 .fill-N7{fill:#FFFFFF;} + .d2-24141272 .fill-B1{fill:#0A0F25;} + .d2-24141272 .fill-B2{fill:#676C7E;} + .d2-24141272 .fill-B3{fill:#9499AB;} + .d2-24141272 .fill-B4{fill:#CFD2DD;} + .d2-24141272 .fill-B5{fill:#DEE1EB;} + .d2-24141272 .fill-B6{fill:#EEF1F8;} + .d2-24141272 .fill-AA2{fill:#676C7E;} + .d2-24141272 .fill-AA4{fill:#CFD2DD;} + .d2-24141272 .fill-AA5{fill:#DEE1EB;} + .d2-24141272 .fill-AB4{fill:#CFD2DD;} + .d2-24141272 .fill-AB5{fill:#DEE1EB;} + .d2-24141272 .stroke-N1{stroke:#0A0F25;} + .d2-24141272 .stroke-N2{stroke:#676C7E;} + .d2-24141272 .stroke-N3{stroke:#9499AB;} + .d2-24141272 .stroke-N4{stroke:#CFD2DD;} + .d2-24141272 .stroke-N5{stroke:#DEE1EB;} + .d2-24141272 .stroke-N6{stroke:#EEF1F8;} + .d2-24141272 .stroke-N7{stroke:#FFFFFF;} + .d2-24141272 .stroke-B1{stroke:#0A0F25;} + .d2-24141272 .stroke-B2{stroke:#676C7E;} + .d2-24141272 .stroke-B3{stroke:#9499AB;} + .d2-24141272 .stroke-B4{stroke:#CFD2DD;} + .d2-24141272 .stroke-B5{stroke:#DEE1EB;} + .d2-24141272 .stroke-B6{stroke:#EEF1F8;} + .d2-24141272 .stroke-AA2{stroke:#676C7E;} + .d2-24141272 .stroke-AA4{stroke:#CFD2DD;} + .d2-24141272 .stroke-AA5{stroke:#DEE1EB;} + .d2-24141272 .stroke-AB4{stroke:#CFD2DD;} + .d2-24141272 .stroke-AB5{stroke:#DEE1EB;} + .d2-24141272 .background-color-N1{background-color:#0A0F25;} + .d2-24141272 .background-color-N2{background-color:#676C7E;} + .d2-24141272 .background-color-N3{background-color:#9499AB;} + .d2-24141272 .background-color-N4{background-color:#CFD2DD;} + .d2-24141272 .background-color-N5{background-color:#DEE1EB;} + .d2-24141272 .background-color-N6{background-color:#EEF1F8;} + .d2-24141272 .background-color-N7{background-color:#FFFFFF;} + .d2-24141272 .background-color-B1{background-color:#0A0F25;} + .d2-24141272 .background-color-B2{background-color:#676C7E;} + .d2-24141272 .background-color-B3{background-color:#9499AB;} + .d2-24141272 .background-color-B4{background-color:#CFD2DD;} + .d2-24141272 .background-color-B5{background-color:#DEE1EB;} + .d2-24141272 .background-color-B6{background-color:#EEF1F8;} + .d2-24141272 .background-color-AA2{background-color:#676C7E;} + .d2-24141272 .background-color-AA4{background-color:#CFD2DD;} + .d2-24141272 .background-color-AA5{background-color:#DEE1EB;} + .d2-24141272 .background-color-AB4{background-color:#CFD2DD;} + .d2-24141272 .background-color-AB5{background-color:#DEE1EB;} + .d2-24141272 .color-N1{color:#0A0F25;} + .d2-24141272 .color-N2{color:#676C7E;} + .d2-24141272 .color-N3{color:#9499AB;} + .d2-24141272 .color-N4{color:#CFD2DD;} + .d2-24141272 .color-N5{color:#DEE1EB;} + .d2-24141272 .color-N6{color:#EEF1F8;} + .d2-24141272 .color-N7{color:#FFFFFF;} + .d2-24141272 .color-B1{color:#0A0F25;} + .d2-24141272 .color-B2{color:#676C7E;} + .d2-24141272 .color-B3{color:#9499AB;} + .d2-24141272 .color-B4{color:#CFD2DD;} + .d2-24141272 .color-B5{color:#DEE1EB;} + .d2-24141272 .color-B6{color:#EEF1F8;} + .d2-24141272 .color-AA2{color:#676C7E;} + .d2-24141272 .color-AA4{color:#CFD2DD;} + .d2-24141272 .color-AA5{color:#DEE1EB;} + .d2-24141272 .color-AB4{color:#CFD2DD;} + .d2-24141272 .color-AB5{color:#DEE1EB;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0A0F25;--color-border-muted:#676C7E;--color-neutral-muted:#EEF1F8;--color-accent-fg:#676C7E;--color-accent-emphasis:#676C7E;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker-d2-24141272);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-dark-d2-24141272);mix-blend-mode:overlay}.sketch-overlay-B3{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-B4{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-B5{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark-d2-24141272);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-AA5{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-AB5{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker-d2-24141272);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark-d2-24141272);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}@media screen and (prefers-color-scheme:dark){ + .d2-24141272 .fill-N1{fill:#0A0F25;} + .d2-24141272 .fill-N2{fill:#676C7E;} + .d2-24141272 .fill-N3{fill:#9499AB;} + .d2-24141272 .fill-N4{fill:#CFD2DD;} + .d2-24141272 .fill-N5{fill:#DEE1EB;} + .d2-24141272 .fill-N6{fill:#EEF1F8;} + .d2-24141272 .fill-N7{fill:#FFFFFF;} + .d2-24141272 .fill-B1{fill:#0A0F25;} + .d2-24141272 .fill-B2{fill:#676C7E;} + .d2-24141272 .fill-B3{fill:#9499AB;} + .d2-24141272 .fill-B4{fill:#CFD2DD;} + .d2-24141272 .fill-B5{fill:#DEE1EB;} + .d2-24141272 .fill-B6{fill:#EEF1F8;} + .d2-24141272 .fill-AA2{fill:#676C7E;} + .d2-24141272 .fill-AA4{fill:#CFD2DD;} + .d2-24141272 .fill-AA5{fill:#DEE1EB;} + .d2-24141272 .fill-AB4{fill:#CFD2DD;} + .d2-24141272 .fill-AB5{fill:#DEE1EB;} + .d2-24141272 .stroke-N1{stroke:#0A0F25;} + .d2-24141272 .stroke-N2{stroke:#676C7E;} + .d2-24141272 .stroke-N3{stroke:#9499AB;} + .d2-24141272 .stroke-N4{stroke:#CFD2DD;} + .d2-24141272 .stroke-N5{stroke:#DEE1EB;} + .d2-24141272 .stroke-N6{stroke:#EEF1F8;} + .d2-24141272 .stroke-N7{stroke:#FFFFFF;} + .d2-24141272 .stroke-B1{stroke:#0A0F25;} + .d2-24141272 .stroke-B2{stroke:#676C7E;} + .d2-24141272 .stroke-B3{stroke:#9499AB;} + .d2-24141272 .stroke-B4{stroke:#CFD2DD;} + .d2-24141272 .stroke-B5{stroke:#DEE1EB;} + .d2-24141272 .stroke-B6{stroke:#EEF1F8;} + .d2-24141272 .stroke-AA2{stroke:#676C7E;} + .d2-24141272 .stroke-AA4{stroke:#CFD2DD;} + .d2-24141272 .stroke-AA5{stroke:#DEE1EB;} + .d2-24141272 .stroke-AB4{stroke:#CFD2DD;} + .d2-24141272 .stroke-AB5{stroke:#DEE1EB;} + .d2-24141272 .background-color-N1{background-color:#0A0F25;} + .d2-24141272 .background-color-N2{background-color:#676C7E;} + .d2-24141272 .background-color-N3{background-color:#9499AB;} + .d2-24141272 .background-color-N4{background-color:#CFD2DD;} + .d2-24141272 .background-color-N5{background-color:#DEE1EB;} + .d2-24141272 .background-color-N6{background-color:#EEF1F8;} + .d2-24141272 .background-color-N7{background-color:#FFFFFF;} + .d2-24141272 .background-color-B1{background-color:#0A0F25;} + .d2-24141272 .background-color-B2{background-color:#676C7E;} + .d2-24141272 .background-color-B3{background-color:#9499AB;} + .d2-24141272 .background-color-B4{background-color:#CFD2DD;} + .d2-24141272 .background-color-B5{background-color:#DEE1EB;} + .d2-24141272 .background-color-B6{background-color:#EEF1F8;} + .d2-24141272 .background-color-AA2{background-color:#676C7E;} + .d2-24141272 .background-color-AA4{background-color:#CFD2DD;} + .d2-24141272 .background-color-AA5{background-color:#DEE1EB;} + .d2-24141272 .background-color-AB4{background-color:#CFD2DD;} + .d2-24141272 .background-color-AB5{background-color:#DEE1EB;} + .d2-24141272 .color-N1{color:#0A0F25;} + .d2-24141272 .color-N2{color:#676C7E;} + .d2-24141272 .color-N3{color:#9499AB;} + .d2-24141272 .color-N4{color:#CFD2DD;} + .d2-24141272 .color-N5{color:#DEE1EB;} + .d2-24141272 .color-N6{color:#EEF1F8;} + .d2-24141272 .color-N7{color:#FFFFFF;} + .d2-24141272 .color-B1{color:#0A0F25;} + .d2-24141272 .color-B2{color:#676C7E;} + .d2-24141272 .color-B3{color:#9499AB;} + .d2-24141272 .color-B4{color:#CFD2DD;} + .d2-24141272 .color-B5{color:#DEE1EB;} + .d2-24141272 .color-B6{color:#EEF1F8;} + .d2-24141272 .color-AA2{color:#676C7E;} + .d2-24141272 .color-AA4{color:#CFD2DD;} + .d2-24141272 .color-AA5{color:#DEE1EB;} + .d2-24141272 .color-AB4{color:#CFD2DD;} + .d2-24141272 .color-AB5{color:#DEE1EB;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0A0F25;--color-border-muted:#676C7E;--color-neutral-muted:#EEF1F8;--color-accent-fg:#676C7E;--color-accent-emphasis:#676C7E;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker-d2-24141272);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-dark-d2-24141272);mix-blend-mode:overlay}.sketch-overlay-B3{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-B4{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-B5{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark-d2-24141272);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-AA5{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-AB5{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker-d2-24141272);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark-d2-24141272);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal-d2-24141272);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright-d2-24141272);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}}]]> - + - + - + -Your B2B appHosted widgets URL<SCALEKIT_ENVIRONMENT_URL>/ui/Authentication widgets- Signup- LoginUser widgets- User profile- User securityOrganization widgets- Organization settings- Member management- SSO configuration- SCIM configuration Redirect - +Your B2B appHosted widgets URL<SCALEKIT_ENVIRONMENT_URL>/ui/Authentication widgets- Signup- LoginUser widgets- User profile- User securityOrganization widgets- Organization settings- Member management- SSO configuration- SCIM configuration- Session policy Redirect + diff --git a/src/assets/docs/hosted-widgets/2026-05-21-17-12-14.png b/src/assets/docs/hosted-widgets/2026-05-21-17-12-14.png new file mode 100644 index 0000000000000000000000000000000000000000..f34ffa873e612fdbfd8cd7fe0b3c98bc0b53741b GIT binary patch literal 297078 zcmeFZcQ~7G|2K|S2UT50?M^jHX>EeGsH)N0D~j5y_DX_IwbE8mlxS(~J)%~q)mpJP zQJWwL39_Ec=U(66@4oNnsOPWW?>HXE5xH_**Lj_1&htHA@7I|(dO8{`Ok7NKbaX75 z_wGKTqhofYqdRi(*b(3iUQBF&j_w4=>CPQJ%{zAl^t?Rmom}nc=8qQl-VM0gZe#&7iVk)vWDBgJage-EBc&!F@pD$f{nvz*I^E3 z;kGK1A`y>ADnrn@;04nBB#r7luk6s3Vt#}!I@Y3CmSf!>y-huI z_*5u+JzYw>$f;5rn~QX14S3Az1j{1JYR>ZqSOkSOP`2}ofsgLqiKZno1DLPrD1Ciy zfQ{w_y1VB+K;QL58;j_9k3Tpy{ZjH%cDy@xYiR}$&6katoa zHnqRtT85rdc(Zf+G#%H8a43FrbN5uHs_P+W)2a5Y#3kj$Csgg5(0j4%ojgAxzW>y| zqGuw|HK#*SZr?y%7dMvYY-Exy7u9t99m-%#}AsOEOwsN3p9@xJ1{)7sd=>Uyz+*Cjs$yV zxVP;GYGtB;%-xn`)fF?nbA>#Sf^0t+v%6bwHocTM9-+7~?don4b&(%(KAg_=)Gi*%B+wQ8HE<))4|1q$%Y{&2~Ld~m#Gb|&D&`QOT4ysc*%Al}xo+q7WVTS`}v zz}e4FGM=A4&-FaDNx()x;sfV{vSya2R^#08P>qn`Po7uTI=aaCx6`e;d`6o z_u$>%7Qb{&)t`xF@#p2K?ZM0I^V7a@^M#UBe6ynZJP%EUR{xL{9cNYddoF68h|Cj? zLX^>@pYyN1>V>b|RsYrallmkXp^-C|UComH)0tumJ@@?^>p-$nKi(TcU>#U!^xi?I z4&Pp(^E;{V(y~6rh9xvCrJk$UXyxMx*8GCj%>gOS>pH2rC;LxRFHKIR#2J><7V#LhG$lX>7QSkmWz2Ts~}f>NPtv#4Q%CMGlyY$F}atL zOgu^l5af)o6YVasy>gh-r9p((zx@O^60PjI@>ufY$@$PTdPm~J2GST@51ZGYEaF}{$})9L zma*%ZRvNFxQU9ssr6b}h`~gQnmyX@Oopp?*N8`aMttLKC^^f7=XI|VD@Vv+L{?(I< z7w<+q(3rnq_me4uVI-`O?FyZMPeH z4*Mu3z0tWH*|WQN#^<_O^xAD~kN)D7E&0)xbt)u@&}3*?S9#?K-(iF5V!q>WXSmRT8-_s*&bjDAwrH13zHFq9BB*0;~dh7-}S(r+PYeb#S zI(+AuQbT0@g{TWp&Rjiv|Jd9Mw-H=rh}&W zrZsJjZk#Sg+`YIIyP^roa6FS>a8LL`{-xE6DFT)kd}BdbSveoGWOEPaX5@q$%;$W_ zT``a=@KT%0ZgVKPI`V!+E#@lzm;NuUU*^BGXWM7pHyt9_o0F#RXr?{UpVu3Fw0zCs zn!k{TfuUiifs&!E;me#-!=aotL#4t!mF@JTilh`SbGJ`P25xUg{mNsVk^Pf;*#;sx z%2IJ=_bhMce@^{2nF-U&%vQ+p?%!Q5?H3uq4isjg`UPA}oQrNAVSt`H&f={PXC}$b*vXitqMXWp<DVPj zjc|1X_@a-V_hY$pa{cm(PcszMWxIS`pF-q%ZJsRuoV$dMCeP2#f54UvEOlL5eQ2FN zALGomJv!2rxL~ma>3q3-W<|37YtLL7?vZ$H<5hSJRO^%e(}79s2j7cj$2=;Fa?$v0)~U z?>%;UZ2s0y&qhzJoAS7Hs$*(&s_qo>t_W(0;(@x3;?hM13_^acZWttzZN((w&j@HW23_|dHthxBzrQ@f>%@&LM68BDj zyY=n;qu58tuLL*?S9OppQ5NZWWyU=U$){{betG=JSua7JIgE0+ z-$EvhA-XgR@8f2Q16=~dcc^4TGG7?{@yjWvSGp|`Q4WcqM3I}pCFGK}(x8{F)-Tr$ z{TvA`D@3^-xiRk}Ua{W9+3eY`bG+A8g+)wmndp`X+M!!C5w%-8NZHxbJRYq?Udpy-u!IGF0`O;oXs24rIk8#3*$&#*@eT7 z?|!YgTYL9W@AvxPhL)E*w}1brP!o$ByuN4DCSGeYZ(sx_*hzS7G+SvINt>qJ6CUIaFdJ}x-tL@v8wtrglT#O^umRaLY)ce^xf^zyimxA)KaJ?Grz&Ff9q z)yz{}wMT>2Wad4j#!ghkxsj?Y%W7RT#$)2S;7Lg-uM`pnzm)fmrdrPUmE%s1Pnay| zAp=>Vx+CBs<0|5AT^Uq{@EYd zliIIiWcfy5{acQ65)-ysaQzsxGU(}-ox3#6jbD@ciJ5#-x~_HJK^;pj*Nd;aIs8C> zQs#ybw&VuCpIv}<@z+lI{$5v`Z+@k7^I2#3Cj*;;x28QCX2d7(2tC9HWvM_je8=ucPwG@EVZj#Rk2;0g z88_d|97Gt3yMg)0?X<$dItl1R;pM_3U~yPF&7NdFgzTh9P>7hhS`xW#>pAr`FMlFG z8hW3)wS}J*&k%P(jl$ga*r}^)DwFl0A4Pt*g)rV2?v6S^2lhA`n#4fIvWC89%SKZE zej!3BmnV$&f-U&&_Xgzz`5hYH7&FaXo_@HR%^j6i*CI=2lSOwqfT6$HE{kPtV3u@0 z@$_%dWBu`=ts0+oj|asIEd5^$OFgwr^PP{{B?_ui_%3CZ9RcI9$t0=(qcEnZd?R02?z)%dOfk1e{@&<@6CZv zN*5h{e4fgSi~IZgi}~La^YC&ImynZ_6TcxTE-85(xZ}Eapu3NCz;$=;OMiRFKb~{f z&fC_@>8X#Chr7W3bFFPWe0`KIUfl2KpMQTFr(J;4zj|`_{`=PgzM%O26>$l%8{+?b zHqcaY|E#>8Q-GbT>0Ku`V9tO(KoU|iHx&PB@Nbv?)#d+aYVxn9l5&#&kEZ|Q(*L`u zp|_pa9S=94QyT7~|K0z`T>NdK|2hlIG>A!2{GY1^VtTSOwJ$C_ zPIq+;fOkO5_Wur@2L4_9+dFW~uoV6k6{AE)r$VQBSJfbZer3YHl5ODo(J46iq`6vsJ6BT}cbSR!j7AU`ajO z_8HNofIdq|O_a*5afu-!FjV()xslT+84e#iC7=>YNB^e>Ce~rj45K2hS%?0##XlZD z%fK)SK77ztAKr$B`W;tYe)Z=={9A_%qmzI9rT#I*|J&KWNyGogr%|N1K2#hO=}|`& zeg(OC?G+2}neC5i{t5j4mH5 zhi^*{J6;(y4_IOtWlpZVeE>ZWP)TcJI>EmOt)UHKH-1&)nilwBdgp$CCmA!>39nM5 z;o8Vi`HIC7=q-;C=fLWmGw9=v#&6upjvY(`A~^!SqGLBknbG#2SBM;#r;IrFVW-Gp zYowBGW-ZaOAys%`hG8_$8`F_=AQh=U!}#q%>N#kT(kb*dOtuBiTiQgpGLrUi=4!D9 z@wqMTIcs##HuL=wEYn0nsNc&;zSv6#F%$wt5C+}x5PwBKUGzsqr`}Cpz1zA2;@83t z#mI{h6v&HbmWyrtFQr))6I)mQP3-=+W=S-*{-{UoX(DE?kWa&qG};_#DR@$O zcWbz&-S4ZC!FPgqnq>j`h~R;Stmnnx4-U3dBsvzp#}=In8clC)@FXWXB-}=`rEAfz zMijH!s~$*59)D-7<6ZY1hwNf(yNxLc)$kHXksIlx=dv6sQW{$>(r(@UM3jD2(pvi1 zfy`A{@99ONGp3R{&1~DUwe(wLZOAV>>j5OJh(JO0%SwZa8;9k&LcK9;%B`rc8hMC;{E;y;bPr z<~&fq%VFuSRc2af`87HC_Y1}{<|~jh|8O?{Hc$Vl$E+y^l=5m5=awOj3DnM(3?3u! zPJ75q*4da&K`T~2D)@YxvCQEC zf_+9k`se)u-AHxqBz4vF7PYLtOzr66ORrn=OmEu8878YyjzmYSX(vm{wM6l-OE~D{ z^_B(pi#Y1}pg9gUmN?6)=g7(M_K*;FJF6DSPTD7wC3~{}h%4F z)IGBJ(yM0m6eOGir>MPqNMprBIPlk8x~j{=pHhLjPLN-j{SwSyyJ1ta{?k&zdv9yl z9!^Qe!ZglJ;9nldEUMUX?5t{Pw7yk6BtnvmccSKx6`ZA2uCCbyeY<$8K#zXa9~^Lz z*%8B4YTp%=RPNkNn;5VDxws4VZ^5D!&y+fJwuwBkdOC4PjmY2}FNd-Tr%}||>tR=O(<}qXb1|7rsFptB z1doRj(F6w0^-J05(}tg$sHW{j&Xf`-f1;Bs9M3ygdTI42S^Xzb`|omTU=$`4E7+X) z+86#S_Nw9FmAvj6EXTQ~a@MUFz(p8kAxa=7D%GOp(P{@XHRliWeaFTu`YyCt*6d8p z=*Ap^D|w#pZ$oB>`t9yMt_tC={7T@hjNBBO1Trj^>hi!_6O<(<@pI2sQ?~ zyA&`VHfGbZ<qgnu&bGtxXKxed&dP4xsJTs@k5VFu18adC2uWb+_J z@~g!>zSLVhJcTfcv}gejssd6UycNzrQ(Fg}e%)}$wmpRq6jP{?YR;5Mbb>!{qTw!$z!%luvG+?~s<#E0Ho-$+Zq!T(x?k20a zGVLjvQ+hV}iyq-id}&)wr_F2V$rx>U+_`P8TNYU>q%W!FJy;H@aT$B&`H`ZPI&fxZ}1?A5YqBi)vB4xC7)X`)!&o7+g7Jy4gzK0_ksSl%otW@OT_q*w{;c!*S9K#$sZe{Pv`T9-VY)rtKHp5jc5kZ^yO%rD zEErTcb+4Vc^Tr{CyLuI4yUQn*p4oOijZ)8&@PsYXsy!i5+GSg6NT}zEE~kQgOEllZ zeg|yDYN>E{tPT0&LkXqa0Ly@kP%mUUjNKO|Tn!F@79&ij& zz||58B?9U>MrxeZ8(Xx~)pET)TFS_mQvM%8T%+9eXtjMYsp{0<;Aj75%8b}IyJhW(#UmlDBnG$uqO_c8_Ak*cJi zOUx7=P4Qo4AIKfL=8UQo7xJMv8&OD|3qcFkI3Uo{!1|7ARBKm6l@DUyG8XE8{BCXZ zFxW4OSL)&s81*59+F&lRl}s-o$LyDB8=LPRMTyxB{6AI<)JD`miJv%x3&Zt~TVxa}F!M6kip znbxQ%R&X$AuXfAe0jJDWRt?@A3ti_Yp_mrrGK?M?+1Z80?}7n&j~)}XgpC{F8Rk%zuw4USnza@#B6ey z9cb0catApa)S80#)c0NC7W;k;1i?m=A*2an#96ew%<^DvLbJ!hU0m>5)N6Ot*N%nZ zpjF>#ek8_nenzZ4RK!w6;de*d?a@Nega|lz`SZPjB4#eBnA(#{LegXI30FqHG7Tfa zLgX zd(RcbD3&KyXqwWk12%|Dy3s7iVZY*u?HV#%Vycw&i}lR6;)TzGcU#50Y2EB3y(=gn zZTuzEy>8$gbAAOTbn>N?JZteg0|#9UQDiS-Ht;6+&<#uYR(!PaJaE z4aCRiPm{F@!UxO?;}A62*=ku_hV4GEwHs(k>C5trt=xF`{bh2ybB7(T!`Bmzf*H6Y zTkz__UGE2}H$bdr{v(voVanT?gvBA^25GukW8vG{SQ+LTL2kO=B)zlhApnnE0VQ*t z;NH|`?_FbyPL_^jk;a{I$t!mUYgbpkUg${Wy;LfUIfUAgeHB7;d%&YC&6U@CnM>OF z4Aym6!t6;L3NUiW?sOq?%BXJJkJ+Vwjo;P#!7ILg+eiV&dwmEjjsjoLQ5!p%+_d8Q zsUPOWE}*M{X{V_PyTaOO7dxz|;%EU%v%f$ex$aYk-mq0y15&+TL$ZNC zDznVH1qy}hCe>5E1m;TP%Po5~m$6vg$!Kc~Ys~QxV!ts{Lm~1Pdry@c>538vLzyLX zCLmg-3YFm-rka!>Q>*QgcGQ{mZ=`x$i8W2GB^4Y)KvvN8# zD)a#|_g%0Fi0{1XJ1fSdPRj4DT(JS~j>Xz^09HfKRn=z#w?6ELUNe=g-aCU3alPTt zwenHUR^1>MtmHhHXBZIp8LeqrFK0MLon5Vy@ZHQ1y{jZ5eiZR+%Bdzv%0(UPI|#RA zRlLe7nn`7X8%$KAp~xnr6*S%|DUl+1Azwzx{1SKRo~|1Z!=4uWL?kMvO)gLa$Iw4p zlgH}p2dN>}Gc)K~*+C0`%8$>R=q3HkrZI8QX%Ik*fIoaF{$ua$Vl zDQNMq zx^DNMEv>U>+m74Q!kf9&vg}7Uzn-n%ncjUJJRe5+M?ey>DsQN#OWN$=7H=tYoybNT zd_$RSyTTG(RG%B#%&hG45|nPSR&tDK`bk6+cT$F$i5N(Vp%23JR^fM-yyW23@tH-% zEhP_rE$(ie-zy5@)dE)jW((5Qs~lr%Jxb0TXBQF35X>K22D-3K4q2}Rw|1X1EL{0# zP^8v@o(jr%lw;d->gLbqB^HZKyYoG;8SQDf@x&=9nD7%4HMy{vEkxF%PTJ1X3#a7~ z-+ZH8spUQ}9@Qn0E};{S#*sQ>t7ndiT}Vq2HpM`<5ddiD6sWd%NSC^OQG{0<7n4zh z3+I2;WSKw%wb;d__q}5n0m7D_&wHIFOYQAdXGDuqV)htWW-Uh~eCo%plS-;p{{(5UGu8XLt3P4dBW+bp1?5IwctLD0}s=wd!A^ z?5E`7pa2mM1kupNJx#GQWU}s&tkQNIh`Ckxlm6bPxai$SxZuqjzQ4B(2IRLBW6qfX zVq(A6TQg@?9Ap#?sdwO?rN^r=mSsLj<%HV}~Ej$WP?o{Gkm6?zvfTlkpd+KNS$|3Ug8l=7-$}GH6-ckn*2LwJOc**RY{}3n_kY^wGPP@mkk^ zT2BVg3{-By7dRrfkjZP|6|3_{zPHBku^Ce^xM?hU-rgt@ns!bMNW~ep!??xX0BMjJ z%zt3srKwQ7*7x-F1l%ST$`=CwX0?mI_XCL@;?^8V)v6U$xQDv;d1};mxrGqSdrrY$ z*{e>PIkkrJ=&$lCR9DXbcETV>f3EZdgc|hy1J;pLu6q*l}l6=%ZzK(L=u5 z;9yF$?Ew3A+uogGi5;wX$?`DmO>w&Vtm^8sBhl0K`XOflphA)#2%O(-EGZN=?_1mj zghSZ$o0*ooDS1JgW~(w0S3AvShxBP~t1vU9VhmqzQog&qyZfRzeP$zdsM#1%liX>mlLy4XH9=eQ+&)o9Ouw$2dqUex zhmBZ(f9+90%s0>x(F(Xz!MuKt@=BJS)u7+Rv+wW3(&{dNIw#+p^K&m5T`q>Tb`}3- zAG61pKZ#2d+;=_^x|4xY>a>1iAo2_cazu9Rn+bvNrM_?T12rTN%qjyXlriqJJ^1d# zP}d-WVd7HhDe@G()e~HUap1M!$%RN}N8PTRKxJ=C{>E=^@mbZKtuFVH?U-UPdy`J8 ztp*EPBtGP$;h+vQla8Wp?#_QS)n^c5nA&n~2u~p@Uo0F>ov*A6_2cqhMAD)`#7Q0u1sPJ8!6J!*-b{ZLZJgr& zrta*YrvhvyQ3!IC62RhW zs=QT=Ol4obk{R<$Xl5dQ$HfPbngutdQz|B;st`N5%@tOI$+3blaIlPJyrCEMMo5`c zq>*U=F->vNJQGa$vi9hd|N0Q3H4;9Va@13QVBX%ep16atIG20N4cuR_-k#4vldhxe zl`8)H#Ly`;TvM68Fc;F1t108$E9xyL!F&-{riVYr2NNs}*xewNu5Z0CvCa3jL3ccz zV39G;S`Fu~YkxkT{l%Y23+LZ)zQ>7ViBI!({ z)SPY17!mC8h6bZrgTDu%@90M4`!B`Q-f>7%$$Hbd)zlPNwxq7vt$Q>Ht(E zO)-z!I2E?bN#cVBu{(OiBTWrd6c|wS$st1kZY)iCA1ys|@wZBqxeCH?mWwKUK6x*uDS7yh|Q>#OW8V>Y$hzntw z%xNk&=QvRT7Ek5=L5qKKvExo1JZ82wf$7*b@)Op>I+7>Ek|6L)Xf`Mj;-3} zZUSkfa`7UUL-*sB`+dC9;mx=qV0Z@SivD6R#@Tp zwLQX89Jph# zXleXQozO=L5<|Xtgq7^!*{MY~!@<&4{zMbaQjhV+iUIVCcIdp|Ie3o za4zXv%+?rAtB^fdM(-wSr+vHFIWj)5`bWJl(|M$0t>34;*CJp1QmUA@9|l;HhaYaZ zvOk~!fpcJhQuM^tT=tY0AkB%$T%#JF`1PZ6>7MF3A=y1K#HwEz6LM346~cOc$8PdT zLnt9+5_+AldM4>!aDPSPH_zF`ke^XB;~q!@Oz??eNidl3nv+05J}gYLX8!>aXMW({ zmaLt6LyYR%V=Cb{yPk!Z7_%o*Y;y~O7aDMZB+cOD$>)qjRAnfkUnq8FNpvdJRbMu^ zb6Yyx-Lw*A$bQoQPqS4ZVTt<}#(niHtubz>D zcAoy$0|c1ZIzg-QD@K3l?~F-7zQK!qFUhD9iGvv>h59k&>ZB+N zDK8G+W6MqO$;cV=s9g`ZOK@xzvn*}va1dX5_q7heP^~)&y#v|ZsNTJ)LEVH0-V4^` zg^&guda&{B_<9f3M#GZzb)0R!A9p9wMDu8w{`Q(biSX;tkkH*4KTl1THHtUI_&DZLu5;bCJ86y>JKurS3ztF|dA~e93+zazRgiPbQhFEqs-m448j+&w9dOLe}sRh_Iq8 zzFn%dtXxQj=o;}tEI%qDKWR=l2gzT{$PkC>%B~D zHliOh9m7Z(Egt(^4EW1AIAnd)d!q^E@iXLmaZmhM^KS=>qRN7Zwc2e9T)-0GT-T}3 z=vQBR)G2}j7X}~&138B1oC0weEW6LN)PCNMs()qOvWlN=Y;_w&TkQBGp~P3URC3RH z(=R~yZ2W*)h#rZI=7c4s1WI7nZEqL&{Ar#|*i z@<{S`;ulQybzi9nf&UEz$YvM~+(D{$=9&4ax}u1x#lA*L!A^}Mn!8wC44hOza_RU8 zQW`XINs*m(Ky``;7j~Z{Z>_%#v$AI^^N7M7?PPJZ@*$lyed@pQd0}fYNn(A3+8s|f zwNk=Y1Ic8^o_SS0#M(cY-}8}?YH%UB4AZXL8fyxKA@MSk&Lr8D1(b+u#W0#!5;25U zh8P=JLm{G^-D`0#vz1p97)DD=eZ|Je&O`a!)dbnA$rwI-G=gC~n~PK}u9RXtsxM=lDm;O(GFZLXrxHuPw&!aysF?t|s zNLCx23AA70DZ4}5`zYB521sVPn@Efi1BeeKAAiLsvhy+u}?}%1VX+B(_C12=d2L5C*1@u}}%XkD#EiBZX zTuWvwqp<;{mMB89Ya(MDt;PUa`^gXut3@|TKu7yuGK}hCy!E%RBp)Msh@b0tU}hc{ zp_jJ&C5XMmqrc3wU)<4TMe(Zcr&G`Cb}k=*?rO4k(d1dj;rurx3wu*jN3Q3dm~^VP zjD+3Ovrws4!%7!p!&+PF(aJGIaNt$uT3z_If?wC>Vd&#K zI|eQ6ur<6EFhgCxBAdQRfGATFJ0v-j+467aq3p8>n7|OAu5vNNe*9yP=c*O;93o_^ z;SsSokHuvmhgS))TAc@v3nY0lJ1Rrk*)}%J#TV!?Ev8TRqLi(YjYGwbhZ#ig3<&Z^ zB?Mt&{f&{Z=R1^b)(>}wHddbdKT(|o2U@u)xSpAakym=8;^ze42OW~pATGveE)4)L zZ82Mwj^dJXZhGOFeu*(mIT#l`{)G5ECK{;qyS|yY+6W?IxMEx2(LkCPtuIz7nv_?u z2SLaAs3`bSfppvc^RkQW@`qo=c1E>(p=Y~3d34yx?M_o~XOt=6_EnC&vw$Bm`EdAa`w|=6<6wj(o8y*`dTADkcv6lp^%C@2zbI)xkWCW znSpsEv>nC{=5hcPDVcY-M*;KR9?{qp?n2wk3?P;p$2--WEeR#MleRyOwRW7}m~xY8 z)n}bZ;Apn|7876M+1fSs#1K_z(Ka|YlsC>WDh`4e*KAne6t|KX%3hOKkb$zu%hy_B zcv2Y+J>H;8r#$3G%f_zh)J^eU>G9pKNKv742%DYmhQM`SK&$3dm!G|gWTnq+5Y*-5 z_polde;lXC9jCtr^aB_ORrQVnzJF2Fi&H|$3Q`mm4@n+187!9330 zM*qO_jc?ZYtQjL!>RH1YFHM0t(t;-Hm2EG^%`(kJI0RN`laO$5|C9(?!wxrRJ=M@0NQ3XZd!Kf zqJ;3@0Bm!Eu=aH5Ojp#&l!`8gw>hOm^s@=4>-(kn@)E0W86@87m74k!DF%KJH@u~*@&-hkiStw%)IDlzpfURjmDX)knluIxFD5MSmW%~X;y9nR171O zPJ%#ywWz-Ba{WX$$gfpOLN52-rx>7?DC(!MKFqf4KlxfYm{`6Dbudy2+RWIm*1Glv zwhqH^&r5_`BTwq<0yK?D$b3%#G0tIADwFEB1T$EH)W1`+WaV2|Qw$;vsQsR~elylG zm?t(`g822i^G9f6ykP+h2sWq7^OF3TDBms_rs}X|aVXxul%^Coy%TVOc_ah?!zEni zJBCG>>2cm$P7lR%jq0Y}5oW7h-Jtv^aeI4I%=F6KY_;8zefAg_O1#rkW0(8Y-3rXoemzaei9B2>l6zO_7V}SF`3_Bb zBJS9<=Uw#8;i{==Wi>6InMBfVV*OPn)tK}Ugv{J8znt;LlHf^dpSREs$sGeSZN>)M zIUQAVx}B0mWl6bN zn4*Ud$IkiauvJ)f?P;sdjGET_r<_c-kBhHX8{3xo)!2}|QJEJ(K>Vo`+>wPq$viZ=GbxYHNJvy!-+N0btDg3O_g7@HZqF0n)i%L!Pw^_O={w6MDTW0 z89IA8fGG$U+_9u4o!#@3ABCO_%e}-n+4nBztw+VGSWjSr`)+W2!B+vi|Dinq1Eea1 z9MvDd{;&nGk}A+<>jh8Jm4((9q9+i~hImUT*b)-`h}n=(&XH6GQnqt2Dj_ujfcNGT z7^{)(iUfJ`Yz_8FJb~D(K}`X|BEuEl5~*)*2{p;TKb$r{L9thveF8$$= z9yON+&HQU?FaXD^HQ(5h%cE|G>=j*#zM#=`Ix`h);EMD>2+qv6i-8O3*oob*QYylg zEj(AJlMFrv1KgjkN6i}pg1Ba-A&U>jYB5>yuQkW~hA%Uh^KrV#4Byh76VEruc|pdY zl_O*jINr0RC5u8Ql4A@;f{=&czjCB#;wNg#pkf7x;Q$sW&(4Ld8OR0c7-`D$t}3{*O~jB**_XkWlo3RPf!%I)uzTB~simOum4xF$ ze8?)?VGSk4 zoTJwu*c88xlQ0o9}jDL;0Eo~9BqCa#*#db=f+Clc=w>&TT>ie6a5 zcf$8Ft)BG%;z`b*6vn!ADjue-4p}v2Sz|c12ZB`n#5HeNxbOs@r04_z%I9@ih35|ILUnL(L_5A+HUIsNfLve;iBL5)K>o7y%6YGWK`?4$Jo>(!@E-SIll5#2UunU+IQCeLJ3hHpqI*W_R z?&ZFpHb~6r*6D_u3$0N+=NAxOu14qlSG=~7S+8M!YmCKxlO(Zazn4{D82u`O6AYOx z*bh-QLtQl63<|-Q3Ku`+aAZF9cH$9oO%}E#LN~)W6}(I`n1+Q6%*WpyeSwt;*BQg5 z8XJo3EL{;TaI1>XaYSvbqz8t|8rp!@@6pd!nT900mg=vR(B9z)J2G%EV#xTnqx6M2A^Hcyt};x8IqX$mdtfq7B&O z8Pkbfgo?RQ?~qyv5B`@J4f2i4e85HtPAQ0Eaj<^A8B^F$-JNp%O(eLj~#y z6ekc)Voor)gJEN<-D)q)!I=4VyRtsQdjSdK@!Jaw%!1V&8TnO~9Xpdqa*v*s_HNm- z8T<&#)4NG}ce`~MTNFG0Y9eI$36Oj%mqXV+D{P|j&t+H%VspnHDo4)e&$E__%gQVq zB%J*lLj)uOws@q`*b;3U*P&iF8mxxZ%&YubU zN8YGb4UAjE0SH~6KI3w~LwWdUIaWP#&;@{6_gPk^zDuKcP*pdvwM4~p*(J`BHj68_GMfe#}Ec!HhjTE>dvucw?^|Nnsz}2A1#79v+uO#r_WRJ6{YANAYq+mQuG>H?ZI}Li>w`Pe{6r0Kjc17z{+vE8;^dSczA(fG&|xc4L zjS0R4`}wR1;9R1g7d9K}g8NJMsTBLE|JB_5)T6G*VNbYd{g~^+POZ71BoC%Bog`UM zZh@lAwiUp|t#S5D!ff&g{Zs&`ig`BppI<=SQtn*QMsD%15eb>-UWonZhhL`K*w3bO zxa{2kt&MPl|Mke?5=M_FQy|Q}VR91=iSCLw~bo*# zXv0>6gVBf?C%#tdZX{K0&2Hfi@OOL40^4hB)~83SHU8X<129sWC(Pg8);`!XOPI)njC9+dX<>1`d+k!VLAU+Nh#%2Q z$vlSxezmt*EdkZyH zs(U>?GadkyJbWxKis7$J#FsK)XtUIs>S?s%+x^+l<~l%Mwc)=0?9T%S0hPyg=dzgM z%5v||t^6SBs#NR!5d1Ge#($<1gx$aP*Y-L}GY3FZ>=PMS0qhU2gT+&8pUGmEuSvxB zS4GllFJB-YXf=-+JpF4qWvr;gzio%>``)*oy?+Yo!hPusS`}`FB-p)Y7;XRZ_4>ia z%Ov`bEpa*ZH=~CCzUk9=QLff@J5rq~K>6TqV21NOER z-0sZH5CrzU_I}y>qYbr6aINZp{1(7JHz4WJA5N{Ltp%*4rtTX$uM};{vuCnXSu-}M zM!48e;D>=JhEcmKZafFkWO@cW(S7r|*oSS{FAQ-i`#ngEnFKhd!|5c|Vq(KiwZpbp9Sl`tm-w!u-|u3a3Us12^2_75zV8hb^x0&U#e#V{1afm5`NexH{Ui= zY)k{-(i&x<+NedLes&mD{K2*@6)`Xzs@oB*+uh6M-0V!_l=is?KuC(f#_6;ASG9$i zJTg!D)joUX2v8Vq0SpMUGFRUGA$M*UqzgaRt*D173cSt7)?E-3?5uV$aXR)P7WfSW zxd!g|gJ>~em~#XL(k!*1VKU|t5s^hGZIiTM5Np0rPg50|wcpDa4yIv6Mc^OA$iG`f2r z2Og>-cl?-R!r2<@gBiS2SwX zdhh>X=Xz&=-mZMkV%_iB#0i)P6wNrrp9;<$Q@(-6VOLl*f9mG3c z>~|;p8R+}U_$~cE3|mx$m;keVv7q38k@n`{P`7W`c$5@{inLfNZOGDsva2jlk-`}J z5+eJ)@0xZ?^{DJ5+hB+>c0wYu?_wdyuppKaK3(h7{rE4nOy$SN{H#9E->QUu(6a#hJpdA+F_)6r1t_oa{L*6>I7Fj_L zx1T!=Q!^om70S56c9`-Zbpa#Vrnb{CrA5NjKb3L&Q+ps`I#8PLxWg4^Mc_{KORImv zlo$T`!{IwuclgH{XOS@dp`d#nS>(S%U zDvT`hBYx$7!ZZ=y+pJH-X{TX2g`kVr%vdB$jm{x~wqLa8@D8y?_5pbBdjF(%CvU9i}-*nCjXk?leq4Az`}2 zc|`_!>(pjs1wFl#Lw2}fW`Yna@ZBTe<87An@Yd^sb3&#@T(!; z8Tr@$rnvsEn1~h0-3MOY{U=P3T>L@vj>HcCID-Ru>l$g@bK7D17FLkAVtS{ILAVBl z>08_A$J=3AjfCkjs?pJ%JvU40MP!l9F8mDI&ZbH5-bsC;?{*rdX-Jr!$PC#IQ!^w? zkGuAq*lCz9(T4NIOF8`dc1+AxPdQFn3Oq5a=@~h9+B3ABrqH@K1yb(CoG_^g3FcK# z{$`n;dGz3kYZnt@UDS1GoyLFu7>rrk{LE7-G35tl5dO^5%Xj^OEIbuo`qmn6wnLn3 z#7oEL4Q4efna$M^_mzIPMBzQ?0s<&I)e0wVSoMpXUnHwU9W{t0FV+i{zfOts^(?c( zT%e<)Yr&$@|M;D>D_J;PH4sG49Fjla$-no&F_y;$7{#im2N$JX`(3&$T0j3aJXY=N z3l@ZhZj;dJ4DH-seNIim;x5yd2tG}*QYK52EiHvk6WzAOq@%r*DrTA2Wj@sJ>oZy0 z)Y)9s2faT)E>scg|2rlVwoqVF#KWN1|CVh3DuJxKXmn;ybN1=8cCuH@2{?_UFUFW%+79TQmjN0d_^yrp@nvXfk_fGQ);f?Jzg|*PV)8jp(0w*; zEm_z{oMFYaL8R+vRU0FL^XenzK3Mre-J%bbiw%(?^-<^QS>07@u<5uH&p2JRzMS5w zysTEt>Mk=HcB{2Zo(rw#Aa9_(vDBt2L@1Y+p4?I1zMYwY23mZc^<GVqeG3E@ms2tFat!fQlrS68jhAM}l)&sN8bbY|+Z_p2H*>?TxW+|`ptmSz{5 zWa8+{dhw5s)NnZc^lnOdr{Qx0<#n&-y{_$X{bJW(jR%GEN*g8X)9Ec)hUI_M7^noR zF5EojW*l$34}5Y~Ow6mO-auxyz4*3e4S_$S?^HuHRKO4 zd%OHA^2D;p*$#>YlRNFlXn=&7jAoemD%#j|qK_8Rc22p-V{YiCMuhWOw_i1=Q zRpTqKKC1LT8p;2*h5=@WQ?qGE8ro}b6uEw|=fYvD7VWiGpRH88zE0@1eWfAbk=LR5 zO8wpqv$DEo3{7t}CSLLNu|tp&tbRs{@G~Dy$+jJSLt7@+@2vj$EBP(o#X+Ygsmm74 z@sekK|18w7yMAdl$9~`V^-AbFlf*2`26ZL$+U9Zd=r?G0gVY68_VI%jDR+4<#@?K% z=0sc?!;2HKUV>S&F_puMnmmT~Ot+pf1^3#OOQ{V>k$!lQOWE%-h_X{2sL_yEQ&lV0 zStnH!sB}S8%t%tLYhsg517;*W0+kOVSu{aD_b+}r?SgO<{?Sz}dGw_1*;SQw| zp*Enr{4#f1fb0408}BB%4S1LzIDX}<=z#mkKu5e9XA_`cz5{yP@|XA1bAxiYP(Ct2;C-T47+D3dK=>VsAJ-;&AwO z=*wKujNp>8v8-3sL9y4nnI*F)H^03&GBTZ>)z~CdFci2JI4d9ga_w#9vmaups(X6{ zbnq9GJGKO+7JpuaX+Ow6KXwzPyeM!*g${p+6s3DhMCV)n+kF-(!W$^Ge)!3x8`foO zxJac7_4iPE@$cdhBl^)+XoMlDQSh#NXJhn{(qy#u&6j$(NCJXax1Ic{OgUEa z2J_3VbhOZPds^=O+{#_QVTHKT4!dCg_-rh9DUN&(9$_zEt-eWO6k^?rSFc^G;fBFG z?UXx%GSr@?Gr=O{2XARe$FDvb9bPugrp^`Dbn4nkk?%A5sG@4s_eo;Ln#5-^yluM- zs9UrB`%Bmsw`vwt?@-G=?R)e0*|+%aw7);g=j1EN=N#?Xm_2J|mxm8aeIk12PTCVz z0gHrR50sMR|Mnx32i<;3twcLDm9Dhwd-`yP&P80MN}4zREbL$L9zU*r&Jnf0%k{g} zK#J0vGs)S`B}c6W1r18NzXzW*r{{8yU!LyZw+s_^EK`+Sc#{5h;FCO~1XTW@3g6=l z7Wp>4opkeJHbhhNSdU~8m}NTF1c7=YPRtL8KtMi|ak{&s{vYbqT>Eg@8JS%<7V^m~FXC;kI@YRRk_URTnCZWz$FZ-=B-| zK5JtidZ#6d>a-v;9VWg%clUj_u3f1ahLN2B_4mfd@ATFtba=ML&7mM>Ybe0UFWaR& zm$FMd7K^6*HkQ%q!a6D)@gkB}RqEATrbxZ{#bc~O27L{U^jOvF!+WgYPuk^g@5Q6u zcn*CHAehuJy~V_{@B@x=V_Gj3w^4W|t2o*W#5XPNg};KF_jdRFIC*@H-| z*}00G{8zDd7Kybu@82&}AkoURjpGRlG=*|Odke9>NKQuL>?ptHPmEmZR%!JEAHzAtLA-QT=NnI2k&$@o@oxRHovQ1e7Moi4RWL-G$~+Cw=> zLrbJK;2zyNwBz9074T$Fj+v}iMIfE1!>`-?Xk4^DWbXYo&$B3csrOG8kGBu;e6|( z%nve)ar0>^mB1kzmcvQt$m;G!^3f}HAyK+Yw)Mt$7edWM<2N8+x}P87QSNnX{p*5u zTe6CJrYfGxw@}B=MzLV6+2`7adG{atEco%bdCwSemyEyOogeP0nbo|mdzu8#q#Y${ z6S(ka;Rut3Rea_6t)~YrWAcPbm((PFJ?H7Wwg4z%Q7?+@2Fq+UP>F(C z*+%YHbnzB%ybP1>uvrb3`MfmtJi;HpF%joibf*hGqGK<*+;>Bn9&g?hYXghq^d8pY z4x6%Sp5qqfzL7SKm5r`xH3>3cKOiebF(DLBXrAi3L(LT9nOn?K?YN?8tX6u|r>*p? zGE0CXx3Kr~Wqi-TWxXH`kPug9} zR4=Gzu&|2mNJkgn8DPM>&33oY1z%8&wTA!6*UZ$R%Uv4@m6-+j;Yy}1O_`jK$;s5s zZ#3{2V?)0vh7+Wja1&Ge;8WSw*aySeYIeid;+JyFAvKVoTMeEi4S=p)YCn84O4vA% z?c)8ftb0{IO93_`n5cG3UCAJa##zwVG@!%3qj7r2wT?93yB+1gQmYRu=G3)mYPIwH zzboJ;1F~YGmh(du6v&<_SPKrDATis%$?s^9DN!4uR-R=?U<({V9a*m~oW7t&#?(m> zOH-sL7mgvX&Q~$pG)CV*>MHtN&q^qz$ZN$GE$1=O7=v@neLvNkZCqtdBIeoNfcfJ2 zQuUG$sD-S~(i72683v`EyicncEv#;r$Bxy7=faW=l&adv>dpwP4EjFCeY72{V=Ru<+KXOTU%!obqp zSW0~_aO+C7^;gU7++^ow4lnYS+jl5{zKD-l{gRC_8TG7^&;x{WF$Eul4CmGjU3<)2za3Ki ze5~e~c_ONr!ozg@$~V>nnq!YK6+FFtg-$jAopEkKdk@aOzS@{A>G69{;s$()3Z+Gn zy9X(v>-vsA&bhWfP^7C$QH`^OO8r;+E_>nDSf&QW@Ho`|5~qnq*Je3-x*%9etJ|1% zw$@JX_SPfKlzUjN{-nF?{5ts5D8(}}nmE13JPNPvE0#{$7M#YYj4u7BRDR27j>+(+ zKylT(Xi%{Z#YeZ7V55!!yyUysAf{hEe-pz{Xzyog(O3Kpg8ih=sXjX)8XKVse%eAq zWa$QLtWW=&rQ-^)=4{ribp;NK@TlQLz6w+VmxM7|I)-kb&8z`Y3BHaNvok>V7eOvc zBlOc-L(utr)k?6UOXSx`4SOh!Ws$P#yoBb28rq*c#_c^{p^4StMSsy5mPBQDE=hmo zjIFrZBstQV4?KhGQj6j<`lM+JDns?g7%Tfj3eVZY&7B3q!XBS!Z0L&O296vU{Bq$K zZhC}{@#xa4;5AR^6LsO#_s=hk)bv7%Mb5fwAKZ7g2&Kk4+bARCQ=u?`9c8JN85lmYY12Z2yJU6ft$#4)E-1Ow93Hr zzr5_Jet5(q7kcxoJ}_Q@eduGlKIH%H!q0Oijle6~7LFaIlJW;<>-e+q#pE)H57ye0 z-q%17^p~yvV$6RCh0uOrIL~`3=|hI!)+Vy0@N3izIK{&i&OAFsJ7J(S5hH$?JVZLZ zfDL`fB(pq2aekX$UL3hVq>{_+Aho$vjP@71=|TgR3G2`qFSnchwGD8vvk{}8PQwAs z^;jG)6i}1(flG=s)6|mm@R%NRb=#5!g_APACAtZ~mvtc&Mn)gdlcc}Z?_Dm%a=LaK z+ZyiSX%5&~KMrwm9yY}MaM+LSxS-gjus|)?E@q^HypOlj^ z8j{lP&_FuI?M}_~$J;{tyScvae!-OVCe_Z(>FfIPO#jPR`^x>IuCv`4hL1aUTCPvQ zJ%Y`RBE@eH%5BFQ13XDu2Rh5Z2B_Ig0bRnSj<1lddnlw{_2n$}ln|+vJ}1C7YZ_IK zcSB*58o4}154}@`J~_i>rnAtjEvMfVN$O@PDp8Ms6w7;9{ZboPg-k%#cPVcM@ z-xUze4`+5_PNI_oIkTru!gJm$JOZy`21qFcu9oCGW)J;r@mE(!@0qt>98RvQzWYHi z4?s^3z>MRsyI^mTK4?CcY0nkDFilyB#6>gl9lkv@8;1aQKR-P3&yipOF2VKAN5C^p zxbn^Qc=J#$soC);JEnnW60GBMZ7HDusKqBYVEcLiupBE%*&Xm2S=#3(+ID)V&fbOh z$T=IqjFi5wzP#}H$87!PE9h-%!%pMOVbQHO|Ey`|nEv>i2Qy&Pon3K4)Y?MAZO+*T zs+JAZrGvq5iWalVH*;VsdQ@dLOq1?}=Roe(0d+(@^rJ$Y%+{Ya=z$+WRl@UxO19$5 zrXCl&kqOY?c60mvF~%|(6xa_hDaSS!Z1*_WuHR$zy%qG_)))r1I~GJOo(-UL2(BcZ z{D$AXx+LUqiCA?ayjCVsr;41XoQ0;z~9B_&8k0z}?CExUo_wKZv8RdiEEVOjXxxCGMQFV|lSpe`+abEf3kSCYtWC8^k zq7;tPb;WRsd*Cs+l%0U@P&i(%cgzzS8Bu_8(Dy06bYT5G*Piw+#^L*M-gU*Yo-&_e zsfBMx5EhEMNhPb$7>QtV(>2l_LeG;s*I$g}3!V!H2g-lf@r(NYan}V7>#?sT!vQNV z=uxZ?Vx#^3dTx`n6#`pNZlxxMFhuKxHZ!A+a$kM)I+)`|D`3#{=CCcpCityh=>GU5 zmfO|U4=maxtH#X{D#{HD>=PKjLMK=yYTn49n`ar$ZA#DS9LCE!2<%V1p{F>P*X(64 zAiVm|LI;wAq)*oKet;`T!D0jZysuRPlLNe_S7x3~uP83-J8Iqs#5P+)yZ$0nX<)MK z=D81g577o5No-IkC%Na8_~SDlyDa+aP$?u*tk>LrRW4_KJshcxu-a6#m+!NFrjCfj z)aQ4z2(bdEn652#q>@nxKUV*t*cYxM{Q~bLP(5EO=C}~YMm~0fiM-Py=Ll3jDLOYx zOMN?2TVEWy6~)G0Q9)51~K?CM^6M!1Y&6&)%Ya&%Y2_$X+>-T)J2|53>CFeH&wr1su;>83iIr>a%lsGZv8H<08e#C37~8~>jW*-=ntGFB3UjD#C5YW5{RE*mJ|Q;tUo?h6mw7Cuk+FGL1zU{7#MH$u-O zukNm|V(f>hFhTJT5^SP6aQYIdXZ!|zRtk6dmY7{RfMmlRWcO2EjF5c>sL%4YTesSA zsL<+j@o@09;A98JGGy|VU|FmbdV#n4g*}Jxz7016x`13Of|esNGd{Djt&BIiH`iQs ztFx4EHDj8Hoy*WHus1GVYQ3w{QRKHa#*TiV+mVDowx__^Hvz9SR4a!@jE>NS3Lo3L~+bU$$FNV8%<0JJ|S`?vk5fFnULe<&44v|tfzAIslXO2HTSPU{G$y?gD(eo7 z{k05zl^BN9q47h%CYSK)=?<%Zm=hHLi9Vm2$Zcq2x*O6OuUn;|--cO3lvqBTFZ$iA zsnU=hGU3V~1fobRHQx#{e(ZAbb-MooY*Ak-{8B#1di8uLEUWVR%AjBIeKJTPv+KO0 z>!7k1-p}Rc)$7p>k3yB|(EPGTXp?^Xs)KS_fU1l9zj$8KD`?gsSRX&&_4~(#Oehx> zUM?9rd382afHnGC^xWRfg2l5rM$xcY!!GT&f%hs)S1`!X`eMWdH}4V< zM(E|=051w!SS`Ceq4X^HUSa9aFt&My0Q!h6vCIN=M>{OWMCYt%_L-mIVxCb;IAY zJzRmb^H9@BQZJyl$sDS?AO|ixCo=FC!)xkMXpqDYa7lKf)+r;aT?mI5IBEHe!|{2V zj)$j?sjO~q#HkPI`fCQBg3x4}A-Lj2b}CweM+qP65`OntW%9=+;8?r`erh zSng{ZM$ndXrmOD&Fm00G?;16uSq}8FWXEQE1KovK_lGQc_ZGHY2yuF+4g{dVNx3gwKM+Z<7Aj)ih~zehgMePhYo^BIA@9dj0@X>6WE7r;6S9P&2-TQGhIERU9S*8 zcNF#8^ll5@cWuY(DgcPnoGjDHwT-x6L6)i+q`_Xx#I|$$EWH7Zsa=CtTt|J`m@Wj0 zX2ipJhZ@d_K-_fN*L>QtFOh+L49?W#m(>6|9qrgy%K`9goRXM~51P%X7jz1L8!A4X z8t<18V$(|~Y|iH6N>4kJgB2FD8|b?SnwWZ+Smsfocqx!Oy`cUEX%6(hjdfB^uq!yPB~JZwHI&HrZUknHBjV>;E;A;k#M6gGfW zt~l`WsDLGQQV$frE>&ZFjO$fmWrCT&1Y}eD#n5QOsn#TYkw;)GfrUl@n`}PhI}yI_5KDStMQz$_)gc$ z6^Sd(6^5B7NEHh+K^P`mbQ;zb_&0r7v=dgpm{1C?3)^Ib-UbOlTFd|YEB5YzQm_1U zTM|Dj|4{mnm1&zhLltQ09Y-%|88N)%S2}6S@E5c5m3qxDC|cYHe&q=wrZ>35ess8 z*?HM%T)7xprXV>m2f9(UYUH}7p}kVQY#=O`dMi8)m7qiV{O(>3Xp{xE8@0-^)Idf- zVeYSXt)E|%&Q~&4cwcQ@DBs#>ddkE(eZCa(h@QKl-F6?eP|dEtg~(YkZUa+AYdd9L z!WI$i^~b07=yq3bnt;$)^Y9$Q=7Wbb_i`|0a{(Pj@LqG2VU(bBo7jLzGPeQb71CMR z2w&3Xgl;1bh}mu+fhMshsB4tD{$4N(P7i+fMiqELgN{@UuZbA9z=eA<8_r0>7PPWJ zOVpu2!+rR5`WnDaQFrd11vpuV(=l-1-33)9K38*;tS*0|2}sc~kUey8#F|2dy~@LN@erJi|6_be9* z9+mHrVs>05p&f^q+W5YTLqA~Djv!=ATt^}RSjuc})84AL{a>6W?twq5?I&5?rXEDF z*1V5k@9Y6DN8dI1m#hvQc|P~00N${bvfZJmbQF&OA^}Y(&;=13()YvyX&~mIxfjo- zgcg?4EFOM((i+aJZ8jf<|M{FxC3PLKJ0R}YPHSs83OHhsEyMj{5}`K(*pZ6WVUuZ~ zm|cdcMnkb7cLfX2UT?$|{9<^QVh1iaF%rK>W-ri2kFSJuI^U`UZx(5r#dvjd1nSFO zk!g>K7;})|GH0?F7C@uAn)!hU_{av7GKc;@J88(a=`~J-%B}G=<=?I;IZ9ujc_8wG zyj57~Q7@3&d+f?L#x=1ZQUFy^P{6+mm|hFqp~|R?4pw_kV6%jSY0ClbmwRP>&E-=} z$GYMPz+=V-=J7eK%=WaQ_%!Er0?Y?lPibBh)j|9M$}~E8VAY}T2M2Q=^cWq>Svq-G zM#o~YLo$`&natORc2U9Qn`u-LXq({{NYZH6zqzVjO}r>gsA_bLKu zW;b7kNb3?oTnQoe&AO#B>ytcfIX?Buvbu7XbXXttz<3iJ9I-Pn_Ew3DDehw+kU8LdUKw?cki?tRz$ktmg3NG#qE8tL|U#D z|C@Qke29U@ji!?);L^gRqBFD(9q?1?iLu_le;7sEyNrW%q!7A*>(6=-(1CTfim(LQ#f*gs z9j3)r(ZRau3syE2RBV+E;J?mYv6x1>19v2Ugb>S4`F(KwKU2+hUcx~oezPpeJCIq81>$=K#e;TCR-P&-= z&+=h07+yNWqfiiE!u^*V1>UV_jp}P2=kosGz>&Y1@*#JKaFeKDXx^JU3pA$7Z1?3< zN+u2TQsGktzvVngRIjGMm!+;VEL$^1~E%_qbhK^ z`8eI!PBX9_Cchl8WT01#5f|AP$bYOq^+BSM&#R*X(*x<#E^EKXNT3$D$vx(d?v!LL zKp>d7K0@Ivqc7@KxC}C|UL4}H;-Af&{)w&SWLo3<8$tZkmVPTuFojj3%_hMpRoswf;TMXp2;2v)63h7)L5<;T$ z5zBIlHE-98kG#IB9Nxz^fEeF`;LAs5;pEH6vyqL4$~iw6c&0T(T)iMqey1wkqY%m! z^NHK;{~oGZnAwZ}zjpz|$DA-^!$AJ?1!IH8bin2Hi<233wG2fHRxoGqwBKi?p91uw z{7H@_xbz#WcMzO;@p0m=QVNxDf#qRF$f`a68tX7KLVleKVBf zV~;;!Jl~?_3^*NM@kVoJO(pNnthrpnam4PLdi6YlsgEhLwW1Ei?3lwTMwkKI#*fZz z95HJG3FS*gO(-`xunw!hk)BqWgO$yH-1Z%zzOAlx8FnPn18K;|rufv2?I*$oXF@){ zd}|=`#rOiaBMZ8~DI}$303DAqTRiF<6@-M~<6N5l>p;Hafr}(UE@4&93PIR>SnUke zIBB^t()_;1-~kxnlf_vMAX7xK^MOP80BUqvwI}-A(dmbV_5%?b+5a#r2MMyV3bC^K$f@u8co&v2e4{f<#>@ihu zthR;>K>?H&$!CzR;|d^*NAU&KAV60oizSE8)k^w@Ep{N|R6*q^(9HG~SKts^-&5@cQ6Ljg{Bet|R7=9<7;tk^xj&W)h(|e{ zih5)#rUA~^lpZ=oq;-j&{5V+Tl76!9^Iu2M4wA%zrJed^YN1)gJ5e@GNZaIjjux!R zQSz>%aY?j*8MTWZ_Sg@Dmm>#853XzFq78jIP`8*pcPuo9!N{V;M5O+Yr~klR_{M5d z#(ndM9(j15hh7f>(RYIC81G5oBLKtm1ETd^_km-KJ1(oBGB-XbeigoLYuy?PsgSKV>&7-UtiD4T!d?rcR80O63y zKab9$4iTz+V(-8CAXFskHXQSFTed&f4`fd-{WZS5r90gdCS*@cWOCU4S(>x3G_QuV zFYT~d+TH{e2p;n`&MM38Ko~s$uXw{m=F9u-SKQf;uVsg8^Jqu_v~S!hC0MjPH1x>f z*k+YBlp#ud2~|CMJA_`_c#4EZ1ZT6|un43?;{#hs%Sf~T?<2!Al zk+mG<3ebbE6M}=Mg31lOF@8+_VlTQ?(gnLLEL@y6lPJtftDUg;q$W(dtKyMOVzMlx)*m$##+ za2LU#BLsFS9eTeRKpBN;wl=jquoBAlo6BIze?Q1^PKD|2q8!6?l@pM{W7&J`~(8~TQYBwH!QwMukaq4Jy!(bjE%S|zu12Ho&6Y9Kpvt| ziOvS~RkM03&#J4)NAt@=`E$~-vA-o&|8(%jVluXtZ zCqj#T7blwX19sCFIj}Zs-j8};088;L^Vkuv_8^RN0h`Ici3@5FvN!zJnS8_-Pm^G( z(iqW1dfgCtM}bM)xQ?Y(yGFT=%DjpJi7(HJp7PVd;Au} zjR~{lygz8W-z~dvHsD5Meu|NR7Rn6h;{Z5Xt;pd+I3`RxfPQCWFib!-R&uySf8}Sy zRq%RxfY0XfOmjkz?su5nv4(#2e7WOTUC$v!4r3S`%m&r^bL7BEv$!v?q@pI@4^Y8( zueYmIBTY?E*%wTwNQ*tKsInmLII1M(3+;sR2r>YCR6u9+eVmY?wAZf}7t~&7-T4J< zP96}D1*bMCq+b19$h){g$}e_Nxm*z|wg=B6k7%hs{_pAs?C(*RPXUj)8xgHrKdbwqSoAd1qkv;|Dt$Tfi95+7;oYzBW1e{LKfIlfEa;{BP zChzpEr=O?EUe~NTe}b|-HMlnmCOqG(0IFrR1Xh2B1bm$cYAwVX$i^?=L{&H_Yt@G! zYF0`}Cm0rYAtB8Ps&d+1q{R`uk7HRwoKGMLcnaSGMZ)^4KTU-fCMPd=rYnni9V5Xc zIWIfYSC|_E!$5L;)g2=9Zsf`{FoQEZ11_J_57y698CG5S- z$Ea{!wj5N_dZPqc8TCS!#;!q8g_;0gG7du;bZwrz*Ku_Nkt@({&GC6YLw}_QV>hsl z_03Dzf>I!EPFZK#lFE^J1=MfNJQCtF%go|)RgJ#hLRX49_Xk%zms7*{L|~Q&y;i6kamBU-uA2w_ zryq1vSIC$|;4V0BbmI!gPjuOVJuU6&x!f8stOwd$hdUQYZ|@5JSej+i+8o^4oWL5O zWhh!R9wWiYFFS@Qzw3n%=gvd$x#c02T6rZRJzk`Ywn=Qz+X*Y9gm`HL!x9}>b2L|> z?Jrxei-ju;*wu=M0vYw_oMe=3x`%bT&Fy0UrIe^vu(VE;<&K^Y1nYRN%`k0pBEm-1)Ja4RyH&Gco% z9`4fas@ygyIH^7J73(7Bd)|2$+xd6wd(OrPal@uKnL#iB@KC`U*SFSd7Zl6o0xpMM zZS$D$>6Lpjjhjo6@5;%uO%u@@Q^(A7{~M|dm^~jh0xS>KVkWdt`ZEW!c7-Y36P_yd z$Sm5Smdfgd@egl|*Q>HB+btoh9hC<;D@i z?mSWf_4Hk{bC20sAH|LZTqjH_vtJ3-%LhigT4O;|tX>MrlP36rz*fVpD68t#@@~(P zelaME4&Q(J1|7a3jqil%^$5m=nQjZvrP>en#D(%m9kc+(X6~=Ua2B0VDK0?^FqOvI z!N>1)-m&D-`S_TQ31z8(sR;8}2P%(%xm3V3*yd_o#QHzy^$!pCEK`{#qUQ}ho&2vU z_LRi_Q2+`5fz|dMDQsa3`KEOE5xUn^_4Ueb*W>$3z1+}p*NA^upE98}UvVhPJwh$3 zEz(SYBcn$kzwhu3%X#3{9ht-ydsgT{W{geZ%KtTqh0fdwqITVkp> zVV!>$*BrN0MdT1+=Kp!e(k{D5HH%n+ zo?shq``WUv;0xnfzHHDG#1R{4x@Mur;v=yT+Y^?(gv>E;#4R7lEocJD8qxU#mAmro z22;fj@!~(nqrttFGbU^Urcu z@IHi}VT@Ni8EZ-F`I)6)u~7nXU(I=CmoZO#eqXzgK=N4bK-<976*A7|1(ew*+h3cW z92>w#R|HpLKW0XG<~ZFQb#H)#*BgtP_z4APKx*SAs-y!%EKBofho_t{N;5Zg3{(d& z(&d3#(u~@-GBT+^)+*;OK0fvvlu%?h^?aMZc>FhzD$8`V_5lqEpy>Ap%y0n@+ZtSu zf($z)D|TVAX82^8^V1Jz83NJ*olVv0Y(zHRc-V<<94Z2fr|qFP;Tcu+%f^%T<@T`c znfD3Ig;UJ+Un05sGhF9m8ElyU=vM2JePoNl>rMgR02bYzJWWJ$HKRHI>&#@?$SjsL zmRPRcoat+0alY$QNQ$IST=RD|-7nQfFHp)${>4w#M>YePHI*`;vw)D?h zbv{WtlkG-#_~6i7e_n0Blj_;|NPW7)QqqU_-+k0&)7Lwb6eSi*TpT?uveB3{So+UK zSj$TA6Slx)g@+2zv|*5b^6#wwn2i&0FJmp2ks;?w3}gR1xKIWKizYv%jqHhI_d zn^PbjAJd>&rm>OIq535ZxsE!wfTf}{t?r>`B;Vi2OnAlFDX_1c6@z4^J|t}b1OKYe zjA5bSURfgVITupV46ax?AQ?bHpL0LVqU=@+Vf9Q|xYh{OH3KNZInTp(f0{p2Gt^HP zf$XGPVnvbGJ%04bR|8h1YyQRT=+j+I;%~lMxymaot)9Ac+>4oSG<|TmeQ8fB%x-<> zx^eQrU!(5JNf)iYuH-Fj_1~Wjv`^a~V|8wSaBd8<}K^hC%i}$Zn zOBNe*fxTV-ORe;LQHI8m_B;Y|2UOjmPbFYCj)c5ackqQs zux(w7h{1%L-|ly@#QR`pwn?}8 zwl`Q6eHjjus?pehnNJu<`b)&8gll~>-DC3cC2&VMB~Ir?0f2+Awmh3BDZ(kSE{G)? z6v+wqosqE8M%GtS0%~z z`Pe~APP|~`y*Mc!a+kSk8_c?$k@UpQy^d9l_1pBwZ}j~2ih{yZVBsTUXA_fOQi~RD z&!p~3h@`B6ESCvFZ-waelniz#D)#*wleQ+A(zvACq0Hn&r|3oj;si0SY$`g~vh^dm(-JNTn;4ZW|j`YFf&iyS5xDkbkx!Pox2x*@pq(idh5;t(cwUdvD z8%{+>TC`nGFuB#msc+c6R2)`WW+`q9T?q-S>94s`-o)MV(L@?u9M8IPii?SjXJ{7~ zG;v}@nlnX7R_~-&#Qi3nM*LQmdQ-dbjS&$yI;-jz`ir<`rqqe-I$}QL=L7>^?=9>G z1-7`rrq%5!AYrQ9QI9?ti0#qOa-M55Hz?0lkPhIcnckak?*?Q*N9A5_HtD;X_2$68CFAua7q_EFL;zMH@=g4xsF%3xmnhVo~=zMVU& ziiTH4@_3dsOQuJfqs8?S7Q4-|z`V^`FSsX;E|E_!DQpNPm@J^{VqCvK9PYZn!-ij0 zbka^kYzTA*4(sE%g~A&8^d+$9A)_Ngm~1vJihy@;m%0L%-ya9| z^NUqva5SXb6LGxN=IF`7)B9W_R5n|!lG`jfpxZ9IxIsrFLwMB3qIE1i0yDwRA6WeL7k=_ zxdX;0X%Q2c`$i?%_@gt| z?{qrgcC8Lo1OZO46>L731IC3MYU#}h>zLvy6*={oEY?OaM;*Z=FT}mF7@;R)~iTC#Chbv>%MZ>>E&=Q6ev#V6vF;oVBxk8SMtQyeW5Jd2~yh z9z6&q(uKs$J_;hij;7wMM!SvP7WIjjOpT6mmEGr6Fo9F0@{ashx zR(^8Dt@~&NOakjkU%$_7a_@Ql-AjJEhmRUGy*5yM=rh>jfgawxO@uk8U$*xcL#aP5 z#1)vJ#9|b!#8YNCj^OlSUps{uYUW5gO|9XkJ~Z(E9}dzsdk$CEoGW2pQXE4j3ht;y zDup*bM7?<_s?MEpKkqAKlG`WGwQXp8x$E~$qgkm#hHX_TowtMn{=LGMGu)?1L5Ay9 zNtLHwXwWbU32_Xl&EL>mq;WvmYJ@uudduo{)U$2gv16p)F9>Ke^&J4nhK&cBr}4Ec zx7=yV1^3{q_+SF|>i}q38*v%f?&vN>zaYjmm5VNic* zhl{iAQ=3$!nW?=)++6=errlIH-#_}9uet1H1|KIjEf8C&W67|OHzP5bCC-*24)a}s zr#`&r#@##4pZ$3%MLFUjT%D6FuFv*>E?FZ_Z6>j<0`P8HZ!%(OaiD0*>IN91@Tlk7 zGx5t^t`_>NS{jUK*)9?Ngn3|J3#RLIRDIYV&6-`JUC6!F(dF zE~T`#{lj{~E`s0l`!{MbLAPM%>a=`?o$Wjr!mLV8*MM&C6O3;|DkS8vu>M68q& zIG0PQH%kNabjq;5rnL^{|BO|=a-vx?NtgSgAAsIISF6EPVre8L7yIpe>lG*KM@zYX zPcD3M9J`b6ci~>Ng?L=rZ{LEtBAE#b2@_7mAJ-e%rct}l6Lc|Go%@>|K5Yy&6^e^G zXSRA=hdX<^I5D})$D7yguq`Z8!yD1q`E+A(oJ-ZKt>|yPe(T zoI_omZe{#)N^Ka*SHw)x4L$8@JGcIt^m-O)`|CGbOjS*0ql~!B%pV-zl=xmYy{ z0VsErgvMa;d(J;6#p7pQ*jhhu*Nct%^PS!*?xo|aE= z4(o!Bu;9gHXJ5U{6<|naq~GZXN&R&b7C)%WZL;X|3ha#NzD;h2PyDX8In7GC-Whh&ZH;2xDtRdj_CsuZPe zq?ADTc@1;fr4%%a7{;YO5DsvbX6~^JvyEh1%n3c8ro8-#*y&Jdtx@yO z+2~cT#sRp=!-GM3N@u!?;LEv$wa=)m(&@4gOXIziQdi9oJ5~JL+Qi3he-paDOeghw zms@e|*o@a}LqcHR=8rQv>~!arrId_SF|FRG8ij6&jlq==KTA8@_W6967x;fD`|7x; zv+jRj#TX1!5D*DlK|u*ANdpW*VCWE$Zb?BvP{cq&#h?)+hVBLh1r+HX7!XlvNNI-n zojd3*KHuN7&+b3_+FhNQ&*$EA&pq)z?{`#H^?;p*WnyZi=R;wY?{P~J6lqjpJuwtH z#TCW{`xCBu-?0}yk6q$RcTOoKZW}uhB+SgCB|2{rm+g{(bH5gb-&p zyJp+*Cf3kn;ugMS=oVA;3v(0um?})>Y~z9%?R0z!N2BvzulV{`P7DEm(*b*W3x6rJ}lusOGu(*@V zCR{;u-eH;FevZ?kefr4I-^uEHc{`YBPKADedM zzdP4G)-)x`e(O%ifoVm+s8k_m6 zbkCsKI#tSvlE}d^#dDppVa}gq<34q!;oNXMW6&8IDSx!Nah~`nnLhvCS(@0DHJt*uq-?!I}CV4dqW z1$#Tfkv`4yFM{g_GquJTnP^!BEJG4@CyrfM2s!eNH3^MsBvav}9^~JA%f{PtRl9IJ zOZ+*VUE^%h6d&9DCcZSP+~t=l16UGI=VHGsNu9{rP8Wow(0!-s8aAEhYrgD~yWoAt z3GXJGFy`c3`nZ@^+6)($oElzi#BpoTFY9`UeEJz6Kd3M?6u*=%_ie7u=@nFvW(2oc z85MT3mGv)y&0DI}S5uniUl{N|v(<+1aV`Mp5|}FDSN06?Mwsbm5_Mj8JPEt)P$;ns zFfL=%62sNLY1!W*#2Z!NtkDs}oL0Q}%>RQkPh zW*-H`qN)YbyMg{0(PJgw$fv3=_G;ygY7LlLpJ{*QPOT0&9bU^ENch`DZsE;*xo_mL`>vF@zcA97hwQn7_NyMMKxk1bA|?t z_@)D=Ept2E#p|bautxM6zAd-rlBB&O-6tzT`bdzSp=#_LwcYTaf$yuu02kSB+!A6~IzkEh&2K&M+SYFfbJ=O=^ zur9NKDp+kT53?-eaHWz|>o-^eU1VJx+~$Yd_eO-)>+@!WA7nao%sKPNJ~b~b)`P>XqJup zTHt2XGL{s8T`8-g@$TAhb@!ot&F6tMRvpVs%TQ@Mu`APb3`x3ki-}Nkut&aE z{(~^g9Y@KIx=B|LPcYe+Zx_w-F)rEWy=tB7GNo7QLQIX&$HmVEeFcUOw|xD3(4j=~cF4~yE_idENze#ee%oKx>?R)_i_hA2 zm1HtKbf(L#c<`03lNi$o^r*94uBUS-;c!=TkNVibe8{WiHs<;JqvK9PEo_n~cEqv9 zabRIiKf?NDHs_Ckx4SF6Pw{9-c5q9(hp1+a0e+x~PHa|o?*phdX~I-Yl#0)kq-W*T z&~ULu+=*z<0Spzy-7#NsaQDJt{?StN^^&AUk!Ss5=B=)i2ACNM@};}qUub$tXjuyw`*ACp(Yxdq~->lEClxv|%q z>?KElqB{-RDqb533;_FyuQ@$=88HbU28?Ue&*?C&(`v0HfP$E>S1KAZJme+b49SK_ z7r%~tZZ42acmBY(tJ6#9XTd;k<(7-zf?!5-Y#r_!&N?`#bY?;4^>|eAoe#M8Nw?Fa zoXL#`m&Y?_y1O&Cm}2e>u0NTzYT2*Avc)=?$JCmp06??Nx5xTTopow5WaC_$<0tk9 z<6>~mxFC*4v4=Omkf9I=0GFqKMnI`D2dHcuTGWlsB^T2;bBxFDg0wc5`Q){`#1!_p zV$wOY1s5F8ZGLU)w2%G)zfR)wRa;Mz-&f&XehJ=f zf5kjx+XQD|&z;LeL*~=@SC1TB z<%tC`0$=F=zAxvv>D&F=*_HGSDoS&zvhIxA#QSuXnrk-*cgkFGo3nOsTCo12xkP`h z#Y}~7X|G0LB;BqfXa;Qf%~cKOGZYKGF;sduskn!)VEQ6q=v!BtoR|KTv0rrZ4@egTlo;UiDRem~DK(WNwA@VW zR@`B}BMN<*`y{h6rFe^f*qn!k!z0dP&FKc0l#E4Hl#DOF!xD@G=_xH-8Jqzfb1g}y zX?cM)=3@DSQ?3 zj+@7g8KBwjf=%-BXX>{YOaxidwH4mXNH~#nB2`0Bje(ourRE>_h2$}Jw);j5thZWeLFjwdw)et_j0Pd1|cB)jVnuCO{Gop+a#&FW&nj*F63Yw5=WG8>&W*% zpvN_B3CDa}AQp!Eg|$Qlud}l?))1&&Fj+JM*0_>z9@~&ZHwcr&r!8jA(6vvtW!hwH zM&P*tQL5~6`Sr(+kd;*wN*=-A(s3E#C(ZTx5!i)Zz;uB9VP`kFmWg>lf8hQ1p7D&8 zIj5;Q{fGe`rT^08Wxfbem^ycS>TlVENRhCKYFD0Cm;-(~2Pic2z4`B<@|Ag1LeLN1m6npuvh~_oxu=za0gdD233Un&Cn~YrH^C;xeNuur z=Qw5~bdoLyoCa^6jETl^a-OA6LG9_7w+(47Qa1&>rEWf0*W7@qzJ4fTY$=b6vCU7YSzi>zvXz~$!ajU9G7TTum{V+$t` z`+X}u`s~PIY@5oY-YI*KkkID760Cc8i}D*y>LdF#ou4y@ohoWP2SiwIVu>lV`C$)t zB$(XHub0$Yvi@?ip5m(I7Gsz`YF2)Xm93B|WS(4{h`>!?RuT^O-g=@Gi-aQXK#8eU6qT6H6;=PdkhWV>#!8|$WX?7laV3of)oTrS|1JCv z#&d7TN@x~Hxo0Xp!k+8!j)q~^Z{@u|hgDzE18`4q94bngpv96)kwR7R=F$r}A*pAM z&iFDI0qgXK!Pxa4pL)u?3zjiN4lPD*f2iBZgKrClK3^@!ozNXS7!aYM5%~%x-ztEX z0_N@6BtGtQl z0WEfERQUXlU!bljmyw4f^HO_U>`AJ+~P93f#f zE5)TY2VyNZ*XL;;PrB{kq@kUnJU9zYB*&uZ`KErp`sd_8-(+8F(b-mkfL?5g3vu_3 z;>ZIxmYI?wScKSC#JbW(D;`Ya{6V!H`Zc7<89yPKws`%xoj+ccvE3_XF zI{g3#VDR2F0Xvj-^Vw-xzPYKNfT^#z1GpUyh?wkh8J3Iwb37oKKY1;YtS2uUG8ooYt_-(hWr`_u%5^?Apn6&ILiehlgh`pG=e3+LAZg{TG=?;0^) z62DS%DKHL!D`pSvr?ikAD3gag6bI9k6DvlAer~u=F`iZkq6+ya0ZP3$a=ux!^Xatl zL?tkp<(X7-cOknFTNg9bh3_uD==3e!F2l1NOJimGn({4RR_LjesT(VifKEHK%@bi_ z@LhF)TgX{4D{x6g3Ao+F^S8&Vsq!bj=Jxv9W_0J;M2VbNW)UgETJhhx9wz^l+Sxwi z-P}YkLAU}~{*!9e6ZLtS!rzRazQ)3aA4f1q;AtAPtgBCBO)LSN$HtUDC@kfr=Xkdh`B_J0 zH!aRj7K{Q!VBwuQYh8=O(TI_RGoa+q1UMCaU=E8zOs&t4sb2%PXy1`Sfdf914sUO| z0|h|jcn8z_?)>PW6IAucE$||!BF}UO(#7P%0U3rXcpG=Ay;&%IF+R^W)^<|kmk3PTi`HqLy`+i1)YQ>;6}J<>F@bWcs&S|n_^X``FPCZw;z@b z`sOQy#j9A?Y$)Z)@AQ$2wSPcgx7B+*0lG-d{UZ&oWE2ZscyXHSII zH=DT?Gre7$Y6(3qyb($B#6#RHhk1~E*IA`E`r4P2 zwbfgnSH=)q5CEss{5Zn!4Fye@2g_CfmwLIQGV&bkpHnv+GWsXZXVE zMR!AHS-2TNFxJ*yV+7Dm{DhF$U7QgkR?3ZnfLM7Y)IXe1s|E4al31h-(1+}rG~vX% z{XH>?M9q#$ETu&~$vVKZ4Jdw+u4XSYrdTdfzFHkkl}Lv$HukyleO1Y8MY#AMeE?5m zy9=!9T_dbY;s&4Sf&q=fEG?M}S}U#l?%YC@n4rHEEOh}Fo$w_Y$Ad!+bFP7Cf2~9X zo7H&tRXmI~EBjx3*8ow#V3L^^hW^Go+oCHur7;jn`7!Te^1&LbM#_5?Vb5uKNU|MJ ziqm{|&?|%fx@wiNgl5kNN|(fv_MN*`*{}30z(hnYZQ`Qq_%yIh^H4`(B~^)GGLzl4 ze92OCn6toj+$M|rGEfk7K>xoS&l5~F*yD?)XqnT(rpfh4yS{R}rG zD?6UizZ1Kl`oW!lM1=Z4mN|bomJiQNiaIg)WdZC^bVJ`BMNqnWz8mamZUgh~a|H8TvJzO?KIoh+{q& z&}(l+oylvPcsSh^viS^%y7I2r%Qh-;Dcg7I2J?McX)D+!c=Qv=uUCAq$T523kqGuQ z&j`<}bSJN#dHnjy70QB$Yn#$&>9*5diF(b*zdntEL+$Ou-4Cg^pYsrBFS^?$`EYTJ z6q4~u#9?e^)S*B7R#KVyH7e@{*o`XryGx&O4ipiL;M5suHHhy1Ria@#{TXmwNt4 zoF{QM#`1DQNwbDZ$xi#FUTw~yjF2+wOqw4e(jF?fWR)y_=XUsXG}ejj%vk-p<{Ox5 z<8#zozydJ|oPxsoep71b2VWtPTOA8O7?g zqy{Z0zT>OSfw7NdQzu9tc#YobTg4eOy)ndJ0FSNA6nDJ)R-K z8b)sJ&oj;W`n~%a$3zI$UsvXv<`6KQ$waW>CSAg$mbg50C5vfHTm)!L3Y?ui-1HToe$FzJQZzjl14xCb7Y9J{})T+py z{@Y?xwaLP46KTGoBs4!858xELqDRj} z#aw>%Rf@R45*6cL7^V@jS0LpNQvQuC#x!&;9H#XVOtK2P*HC(!}({jXK-UmOE| zt&P+qx)#NaDzcJf)&COxHOTR7C z7E;y25ENO5MOjv5Qo6&=2V=l7b>xpRM!NTkjOsnZ!;#ll^07>Iph=mmnC4zsdKp)j zd@%<@G_;y0Sh~HaIu6&79N;LIv<5mSgJ!h#t`n4<+Vs3{M!^YOPeB7z`{igF(DKkr zelwN09d_YjuEQwqCG9w>mhhl{v5=k*_*MsIZ`WMG229uNf2=Aq0a;j1qnt>!@|9DH zRbyj2ljOwK7BMPy+5U>DXc=E*z%fj)6_TU&tto#_j5=lj`nT<=cjB7iFtNLaa zo5p;>mfM#?1|6RSS%wY4R1%F?La9p~kaa$p6GiL$*q3&&jsYvFU|Is*%-|OE%Inp$+ z&zA~C(Ch(-VyjC8!v)x{Qf!Ti0)(V^pfSC3Ofs*t^@)(TlmjO3NG29etpb0G@eBE; zc{&-z59<8XrM8$w&bj1CxyX~$ioMNr3s15ZE;m*i9}xn-w($?;XE_ipyPX@X}P zQ3Zt#txC~YcFURRKF5N2Z7$NxQaJr*B}Sc!*ZTfvqQ}GC^Vq$ySF}COrCf9I@9;I$ z#EW|^VZW6xQVX?4wflys0(p;HY@Afda&_aF0byOVyOpP9eMq>lz_c>uQb!~+Ek<8l zf8=#HXTF%fJIvkw$Xf7Rt~u%xE~LG4ApcSc=l@{Uh~E$SuKmK3{bUyRBkL%+GXs?( zvS}S2$sW4@7Ot8R2ooJ$qBv>;aQkrk#()^Lk4gpPV&(jcj08}1^xF=Fw>E&@PF`@C z^uhJLxUS5*@4(7XF>3>UDkNNJ@WhtCE%H)$G@%JtXV*{L z$z$;Aj=&R23?CpgK`?K8>G?4m`WwI%BP9Z(c1hr!Mvd*3LH@5jMlN(n3@F6fxj+^1 zfT*Gan(;Vt%LBST`P~Wlrw|*p!}Ng_bm1KXO|TPMC062dU;a=!*9Y{&?NC71o)f8N zjebngZ-lqw-|#=Cl5cOX>pQR-OGHpWe~#w%i$jk%LY9CjtQ}%WDd|M%wy|zB%Qliz zmy4LYVR~|p2neD|^)jwbqzAtR2zKXFn!cJ)W{p&s14cy09Z(rD)`I#(60o^~kVt%; z;CkBoIq*=0Uh3k13p=BrdVn_5X2DaGyqPjmfN8(bX5y7vg=-SlD_w^sfG+oc26f&} z9c574!#Y?H^0Qc6hSR)Kjm&qza>;gRbxuVUy`)HrRyDK!9|9uOW!s9CVjt#`>7V^lnB5)lzJhVUJ z{cji?=oH{Xl$7eLvH?X1it4yxJN5TPf#3dA!U0~j{oI@nxl}2^3JF&~s`y#Hh4*FJ^6518ZAwAMBwR0;FAi_{2CXutC%m$&}m zKQb&ZbtTW%-@y>f8P;y zFO)Sa7~MER{<(Kh$0i)+%Wq;d4ZqrNE-)F zE|J&Hh(05MLkcZftlyo;w*Jrl;o%7%;(Ez;iOd`xod@5?Cr&B&ugE5X;X~%^w^p~1 zog2(-^7V(pf3OX|{))s9Dv>RT^=%{{iLc1B`{pK+nce;&+rclVHq1j_im!+cE~NOX z{6AX-^4@x!MQ3bd(Oa?Aifj$alwAXOn+L5uNi- z_D466S!#bfNx$sq|DJt18TgRLoEjtAVRi!Y-6W>B6aQEN2!2K#K4digW#{U#yoo4) z4s#j)8x{^l9rWamCpX+j4@fJI9AJ~d|EMbe_D&K%(9tdy)Au7U-wyOvRQBr&Jpb<- z|5xXC;5L}%x`B0Ym7%q`39oh7synU!w;%fZ?~^zUPOsujpgq~1Ata(4$s9D@O82{K z{M(~){~|oP^5xH~n<#;tUXL~-nQQ7FZfSG^{H)!`O<(e?F8d*{RQ=M*i~rpc|BuCb zJVWP_NBg4(d9mp3!55Y)7zO{EmG}zyTe;3+y;}0`K9PX8+F`e&fV{*1@I_VwSo2d} zXwm(h(TPiu7uttT+&^5<2zK}o&FhME@{^k&O|lVrN{WB}1r#2~;2Scm$H_K9;ZX=? zRujx%`)|%iJePkH

mg@W7dXxI~bcPpc{<{HZV~sE#BDVLoy@$qGpHVpbpq-etpj zXw^#n(aq6$_oeUOo851J8vR0|VST32=a+hjIT8v3)kx7f0h{ogn1_UeAW%(&7MueR zm1sgkwRC0x_-?c$3II=LDJ(gXdfA73PgNqmIxdOJ|K=PwTxLJ|2OiqH*^oPE0E_Pk z;NTFtMm_D?2d!2RWv&IBry$+x2} zJ_1O=ILX~m^3t2)O<{=lR@+U+Rn{Dd190{Nt~35q=?Y}k(XkQ@)S1Aaq=)n?2`~tx z0;%{O7czDn6lK(5B4-%bI35b7Ff^zD(@sOo&maw5rp9kxZu^IpjZT2fHjikGF>pyV zLCgL+5SC;jl4Tt0ZWxMn1(l*xSKm?~yuo_|<#U>n7C2++1J|g~I!Z9Yo9QVqk`LBD zJdDw45{lHBXj%oTciEbjc^}AxSvf$6S^=sWdPt0WD~s@1t@4D|!0?ERW*I~5`y^0y zM!i#qvMmB%1MPvSkl||jg5>Sy+S3jH#qnlmqJF|b?nEKA z718mxe?Xx#G_DYme*>uPg+tGv8i>Mo+q{bS0}njU*+?A~iA*91mi?nI+)Lp^jsS=L zji}}2*%D2tD=a=`B3nEp^i+7S+ck&&&2_wPmkjRqjQ7*S9l`n)ctnu|uomBk_MjFr zGhVi>!;4VR!DJN1WWz*VLQkQ3UsG??NdWG;U4~0&S5APdxnpC<`Hzfzb=xG;Hy*%B zxB$HO6sW-y!?tIO@p`9bvAN$kALn9zK92O$#ODqhFwIcmk$pd(m{5#B0TPC`Wb&>`|w zcpX(Hw%qmmH?I~%b3j{y1l{Ny_Z3oi3y6pne0y@~#&9vx*M?4)=?iU#R{#bP`&tOh z78$@mr3sx-q)oNG|IzomPS`q~^y^3yo$#DX+Z2?&Gd~4#s1wd?%K|+%4Zx?^p1uqF zgGZz;Ae-|P$-6yd;I>4L8B90V0Hhsk>VDw6p#9%D2jlHEK+1196orJ&kTOB7`?BpW z5>#Y!#p;&_#Vva4e3s0b;sO#LCf6dWJN8%Lx(+K@rTs)m{MW!^?H@=iQa|B}IR3wzT1Jd1~_7WX>oVcS^Yq%ZFkHH}CUcLYHa z1s$hswn$lgU4OOp;<>LtNAyt??H3G zLPAp!!|D#YD>2sTB}cVxl`|Q&U6E$_&K7FmgmjoPO50_FPgV0AzrPLM7|Gzx0C|xb zG?hlI+({jh-s1?G0_ex9Kv0kdkEi}%$HC6im~=#?H3J1xHFN=k%3K;$gbdW(es;0) zZGIgaJ_1{v3On);C#h31$c#luPmII5suWs$ZvduT7=0@}u>puGdWxi7G^+X_Hp_) zBB%v+gd0`yp2)YCaZSS9Ya5!##+i!)xk2R3MPT(GRiPfUMj(Z(fc?_>7Z9;Fk}`$e zptn>ZS7R<9-m+Uj^pI5r6-`6XmCOWHoV(!&2NlZj-Fo8pyFuVP-Ex@yfQZbJoa>TWLtUhPnX9>X|)*Sli)A4DVfpTd1B_^vM- zueKo*Xx)1`l&nCd)ItP=`8}MhuqoR_F@{C@%*~HJjG2 z&*V>$!Xw@~kTO%vb|pDH#vt{E0$jKIVlUf%m5Hs@pUDY`1j+;)$^qeqBuXr!Ew?so zIRkXrpM`gZugxgf`=}OHxSStWgP9QWA>K5DIOOrX!wrod6!ahszTk6ZMxpl4Asjyz zd+z0L4Cp6mUkX@-xx&05VjL^T3I%*L z^h{RCV9j72gNt!g^?(%Kr}9DNgxuZ{V4G`0GUaefMq*tSQ|`t3+UxqwN-d+JfXkQcz;uBzm;2p8>*cjGIhl9j3-aUD^9Vt7DY^m3RR z)sTm|{SoKnN~^fecXLql=#Lj*I8`@?+La8<3Q z53}z@MGuFnWbFb(203~LnEW;x9sbt-N$xL$jec}n3J+)?dv8r>0&s$ulGZj?V0LN& z4y>HV5F$OccF@XF7h1CfLNrIBm-@w5+N=3MR`^a>YRF{6<^Mdnff9KAATIYPa~LwZ&QpAT8mI5zao6oYlp%j41W_nK&R5VQ!wrj^ z0~B^05anE7C=1FlkDkx)(*>O@QMfuR?O<4B`0h?Q>oTNBada*TP1dW!@GHSOlRIsr zv6<#VSr6dcOmNGDVpkW?EUbD>pzcFOS_~F!@=%GYXaRURBvBwWvh&n$$*Uo1T|m^e zUhy0$#eFHE2zdD&KG3VGf!<)x+9te*)GkI)H7{EHQH6Mn@X*6jt8^*r`z;>#n4*)J zyFGJv(@rfxO+v3%!hY&R+o957;sd(knOa9Ur9Utg98#DF#>L%5g>gYPr+{?GJY=t z$5H@T;t?O-8bM>$^XM=?KxNzvRRAY`WsQ`Z9zJ{eQv2aQuPYBbx^bNG3(z(PYB@$# zPvn0e5|nFwIe9tPEEKybWy-_sxUbB*$B5@o4>ndH6`~;N9!c!SmKo)}nt|y{BY?8b2A#oDx+g6&^u8*< z_pcDQ02tIvG)1&^kKk3LCA~B#?~XanY9Z0Vc1u-)1o=2wMr8WPfn<(Li28jiZYl|r zNRFbJAc{7cd9u7kv9Vh0H)TDU%^nfSjoToFZs=$d1;kzGNCY7U{o9%(VTa7go5bod5?p!~ow+tMuvxjL`1aPQ ztM-sAXni-OPT8LYSw#ofxFzmBz$06c$CPS^Zf9B`w{91+YaIzlF!doM0_BM32Crh+ zvv4j*VN|`eJ?JQ4E&7n2*Dz$?yk75?dTg-`D$UlwsUU}Z#*+)+GYqY$=@(^UZ11?P zadr`@)Smfrhaxm`yh z&`bm#Q|FPdlIG3exCbs#*v_Z^SlMZ`8T+8NSu-36oAJPDYpVR(&A|QKjOoo+Oa2N9 z8bD~kL3mcI;x}LTfZacpa%9uaLv0{_bv%dG-i@~Ci@jyfm~nqqtyt=2WUvyZh|ztx z0)8vrrp20W&2O#SPupZKOgVCO;c3#E*ub9wDi=5Fuj#C@1-P(g;GQn9e-w97LS)~T zo#aPD781H?yYl#*oxhcxUNdYQ5)QrXFy&erviA2-w0guO`?r8?<6Za?SqYKFSMSu& z4|>F*~TapAfR*IZDak{qh3I>2p2?r32Td&P}BwknE|-C?23KW zUI}e~otMD&rcCs8DE1ttsUp`Y4x~VI`ni~fV=kc32;;J5yClY`B(-CA)@?1eYTvi! zVe?Q$SoZ$lU%!r?_!jk!QxPoPWricG|Ns4YFn}0+g?D~!Q@hR97%sc$I)vm3HEqYrNBC-Wsv{ggG1;}lJ>;79ne_G5dZaA_?83dKTUi7 z*wya8zM%nK`S~-aD<1##OK`QJw)GWf&n5Ell(`7c{fe+ld3^s-`5g{x+Lj(tJ63IN zulR1kXFtoDpL&n_ zFM_V`!q%MY+Y-)b|7zX(`wEII@X{uxnm>qhkR>@sMh@RHQxp2M2iYs$kC=`^b^-(E{M^Vg!V)59Lb zUQ4-gdF?y-Uq;3opVLOxD)YFDYJcqq;Y)XnuDj~}m+8>TTtyc+@WqT@c$>T?Zbr56 z%n|3UzcrS3oQ0k7v|Cp|=5q88LB>xy4zGVB?BFo}ns@U0=@&}}b+gxikpM&mLKY2r zzYhb@y2Be!2pH0kU*IT09AwzSk%}IVe;@hRBeB!ku0Co-AyIAbnjfQv@{jgaDV6`Y zXa7%E)hLV-7NBA2R`1-Jo2>HD>Y18s;QYL%#rOZO1pnTTkf1{g5C8}DZ2iH{zZqZ2 z>RtsaZCz_pXcwGZOIg>v6qpoho2D%H8LyfYdi|Yz$fOGVn%DeA|AwC?HQ0Fn&R^4` zGK$Eg@HWGz)~v|JXdh%!gBQ1wr+Xq!pbG)FfqwCbkC@@w7UF?~)t7%dy;-m1uSHQr zcO}OxSH*8>@$aQ488u|5+B@NtUXi;CYLXpL(lv)D7O6^+rdxGodz+BjFA}o?6?@Q` z`kr|0!$V80*TW*DzqmmC#n5ZTYD&0_jfQ4lTRuh_`#CbO>tMs5Z&Lx zX9;U6;0g>TGGI^1x5U_9>}US7i*R2BF6Jq_jmGW*gVU-6R zijRd=aOTtk7PG!d**8ZxNMlcKW}A;XX5Z>ctmCQfuusz$(cQg3uDkp?Srf>k%4@g$ zcF$}idsfH&eXC(0`)jnuLGWVRMfUmbROUyjy4j$DniB|k^;e!PU=Tj02}p66#sNir z)w(g4nLyw|tT{8P;gQ=Rul{al;_(~_NaquQp&-%=Y6N=nrzh@ObQcp)zY@A^n`JLO z_dw%&fHl8nKh%_lhJ9-G|LIr!gOOdw@2OL19v$>0p<2#@N=T!q$OS!>8$83pq+jiRuVZi{JLA@8 zwsM79h5NaEo*BmLH52*Ml=5e@HN5$&R8x}GPuCXj5ou^Su4{}=-Hhmh`s4MolUd1X z+G>AblWM|Bi8Q5wAXxm~~ z^ifI=&0CDC+>{55d|*OOgJ{4gtwxTeMXQ#rZ0R0fPZH`sbg)s+6hI%}p?eg_-H^&1 z3z9~({vrWwc$Kz!av_v_W6z-sNB#qpP>tNDO4%7|EN=`Sbtn&9TFRVfT^@fUZQkRk zo9{ovmcptK7nnJn84jYYZJ_b^j5sl{djVK)a`v5j_)XZVj`uWVq1ixNo}*5Piy!J< zlPU93;X_tIq`z)yi5>_gxU}4}$pNnaH*}SVoPag)kFA0LSv!lUb}yr7X;uo4dJ8eK zJEKgy?r-034t>ThuKZaTtE_~4Da=6YwOi%Uh$L4XXm+Fa+0vEQFp9j%mJxrLdn32m zD{r#`$FXcA4FLm4*U*TA01avyk?$psJ1F#pm!H{CyE*l7!gIA_W$ii}ZtfjHCqlh- z%a8LL7Lu(UAooIYJdq>dr8;#Q}Ce%PI+i;B-xC}jxt6M4v^=pnw^=#o3EgQqjCC= zCLIbbJ?I?~&*$jd1ermJ5^(}UfvG#)T(UU?tTBkZ8pk6-<47zP5d6-DFa12I9`AP{ zFWyXr@0N9L?vr!v#Otx{55j5GtA#NZ#viJU9Uszunox_1D|{f4gxK!swch?dnro zz2;Fg`V?LBpG8i5#z6nU0FcABO1^?$H$GCe&jla%vcCoRW>CrUWzi`N@xsF1@)u)3?HvGaHuQ zVH4Wz7}qSEsIE28axBcK*Sou?#dYTKog~F-XPb7p+`u9HJTQy#X%pi^?OW7OIgNj@ z&d9fE1o{iqvE70+NkwLLtpK*UCi8V z7e?dEY%QV?7^k&t-LHIty#-E({_#%>zwCC^cz;I%`6IN&r!gkN{6ihximQrMx9+{Px>S?mj*m4XJS`GF-*7{t!us@qf@>?(n6weLi_=FP42hpv8=UoX_{cv9RjH#6GVK) zap0+I_fN<;1r<5!cjlnZG%6JRw5vMg+HtwjYq2`dm@fLNj=4^h^TK62rrFyotQKsW z@}SjltHu~CiQdX$zc|5ZngDaqwngOyFg{4&FW#k?H3AB?UM((wRms!Sj#?(_u3#R| zZX4J=4Xol0QOk1`;`#P-v1U$iTOek;m&x4>+&aTy<56Y+^bqglf(ax??UCbAgV3+F zWt%R#xYvYV+ufyG2t;UDMSAY;>~tDCCpmY zbCoXa3;Hbfq#g9f`iez-m<4JK4R5_@hf#FWXavW%Fz;fe$}^J#E{{vwK@dZLrNr0! z&zSkWCK%-ZnSAiifcPlH_2p_>B;kwv{!K_BzO^x(d>N-Of|Rve?7js^-z!Z!sb=4X zJ+cRh78IDkjbrD*A?r<$pxdu%bk_}93OWL@r8F1~#P|%uf!hT}GaKbHE^$9zteh@c zo=)NNPkcq6tMImilxNL3UK9dcTBB)$#aAp9BE5jrs$omFb=j7f@q48WJwc^AFd9zp z46MT7QU!r#9_o;0Inin50;v5LeUKVMc(Ec-%80CO-#}-s!X5>eX!~KZjD5OJZf^t= z&-plxNYCAv#012EJyXsM5-l>^@?!JX<8Dj?x3%oMomn8m9Yoc*9P_aM%)QNnwJ`T)bHuSU4lZiFAQU>hDH4wJ z3m$u2B4+gA(s!NX!mWYlPu{UqYuXZInx8GQve-F`jWiiMBu97~Pt;6d0WJ8^^Rn8U za<6zkFo%9$0-v7&-OPL&eAq0@```<$6=Y3%jE_LgN;2~{dbgHYYHcNAyfi|NEM@HB zI}Ly!$EU9aB)eznhFYrc2LxF*xq^lUjQ%9LB6@U&FD*CnlUp2jxQf>`8m0?)wS$?G zNZ@u1!-vJp+JW5rsayIb}_ zy8HEU;=@`D$B|ojXpuNs)g-wCM-3zqr&QnML4(M{ys>0E*4G6(FoYwb*^6!Ze)c^N zmzl6Z*nm8MAe=I9OTFJ?1Ne-0d$8$BAI!O}lO;+aSCR@=zW*8=Tx9L;@eP?p_QnOE z!DdZVWIP)fGQIHz|A;<}CrarVJ?4~=Ac3?+Do_ocOR(uNpypCOuCeq3@Fl@G{e+_% zUn@Mob={P$AR+E(KU`C+e*qOI#vL@@DyXFkzsw+YS={xcn4#OkTv)u)TTNNNv*MGV zc?qdH%IdWV%P*89TmW;#l{rG4OV3fioZuW$Ix}8T z?}?z~5B4KE{wj61vx`-U7lfRtd~lbco!8tFBg@R-*7Ecwur%8@Zh2sex?S?ISI(J@ zt*-)s^N*mfFchO}-;9k6-efPDMAYCbg*E3>@r5-5Zob=L5(Qy;=>bRV^IO^G?&YfR9HHRnq-#jniQx=T$OixKDsS1coK z{)|r9pQGC~{$u`s+^#4?EnvE|TGpaPnDPrysNTPhEtYagQpbHjHH**7=Z^8hnG&kE z;1291Z?k6)TAbPIg;Xi&8Wg;YMPoEQHfBMWwHjDEb_yhZvh3lIHhV1|kyHy|%_h+X z&G6OZU|P%HgXrt}g4xil#uB zTP{HWfvGer(wWnwpDz^Ga^h6Itu5)mPkn4k#xX?{r33+e3yB;~a4F6l%9}+3JYBaY zWd&{li&+qEa6Y(3VA>;yL)AskYUT9q8VH~-cIbR}^eUrIev#2ir&9kzC+<5!&LX%- z@G!@77y3+o#lRYR^9h`*S%~=iWZQ3SD|6D%2ZR1}_zw>M^i035zmb{(yhi9u3Gt1! zD5-pZ&iTzoE|Z+mu2)tniv0AtjofFlWnGEXX1BC9nAwi<>-9hQE)%+wLEA1s^G)(B z-R_php428VbYB7u+Q`Fm0}r@W4LjQgtnd|@mc{K`ulqFZ)Gdr%a+(|vx$meHXX(}? z>)jrVyGAq-H^mqcNxoqcd^$BLB z@1SCsYl7p5WtYr_!KhuGlkoor7^>Sho>&xfisVt9hUVIb?<#F&^a(H zIk>n!lfFse%NbccKX5T^TS&Te7}br}0g=Epmnfa$((lbM+_JcgYwG%e({im~aeRq0 zhH64RcK>Y5U{M5Em5?gCrXC6EQw0^JB+jLq9SwO&7Y9shxtlpCC?qH@oRw6@Z<{V? zm0!l-g}JDwGuR%rjA5~@!giK-JA7m6e;yfj8*&~M_-7u~Ht*`KkyI9RZn#oC+$U#n ztdP+r-(9N1HaT6~PPki~qiQ_p!=(A*xJcr~(0dLo_IJ`RKdRV3?LU2%o}cK;SwD7YY?K|ECN&j|b9`vB}-6~-Ls zH6j@_L5qV#Q~FM%kflAI6XCb3Hovb^e7@`>ZddG8uU5KB6gy}OO42_C{m?566f-d{ zW3Z(-F5(2C2M_#@MzyCWeS(_+%W(`l0m!Z6Dbsh&Fe023$pB&CXFly@ZJdpETX=?w z5og&7aL_toeST|5{tAYgF=xeru|-`)6I^ZS_aW)5{q+80t=v@$OKjHWp?$_v+yKl?=15ph~36UX`(Xg^Oc0JzVpBXNoLplUZ79 z$Bj9$Ghdk37Zp8GTn6AprUarzz{(5f-aWBpzCPJr`M{Zq(58D=E8yoRtty_ZmLM3R%l4EVGSEW#JRtbWlbyTsX`(Bp zMVGOod4H}|!N{qOEVCDZ9N14-SryujZlo!oF#ZK3>8$r|TCv+g`U4Lb$nHeQrrM2c z!XeGk4@!=?S*YgR_|ck$l#>(v5}zet&R#zfPS9Nz5g@cY7V{&lv{Goj~{d07%{HJ31xD zmLCo-zbz7v2vw>KzC9xu?elZldscx0p_B3cGL#ksLCBH%>$du_h_pc6X~#lHxCbn3 zRyE|{9cUIFH=Y!`*}$rrH*8lUjE#e?@0pnk&ow19o0ILMVuLJYnx5+I%L32PDr#}Q z5il_3Ir6&?MI5L8RpUK?=5nqRPtG6+{m;@1GI{j$@+j1zCq_GA zBIF&akN{fzm^FQ#@hrCI4ge(TQIo=Xvx9;xB@B~{NmUrkD4;KCS4jyt6=5DwkQE~t%GfM z>%`HkfPTM_Q*5lOtS3)D-vlslV(E7%!JVKku7Z1T*#%TN2~%M2FlukXu(fqPU1lCg zm3C&A7Hx)#g!0KNNYgC?iC=HoS?931a5Wb5e?sn=T$CVHdpmc8X^SNGf2oIJzSsT! z_rZRhrbLxv4+RP0k@(2RBd?cVwcc5t=o%ko(HsePoK4;FrV8&hyGP5WJ(yc%EPs8A ztZT4h-yYZGSLz?_ZvZ6~CEL zFxv@qj$PPX%_OKj&5XHACo3-_a``dpAXNbg$k;=7ABY&CbNbn3_qdKaU*@9a%YSAv zs0Z@s8wj3FFJy^65}lbr`m-kC`1Nb=XMoJJth7~3xc z>KQp&`N=To;VQq97baR~7bXiAKn_{Hwaek)uMt~U15GYHb$j(TF7=GJ=V-zj3yD$8n^PEp#ymhQ~Ob3Q2>pXxs{2go$hGgqxt(?j?;6w`Ii^%CBpu zH7wLYDP>#UsjAX9$|N8B&FNll)pm4+O<(Yn`CDMGB-1k6D1}|^RFHCVAZzXyjG;bH z%g?&8yIC~>Xx5f$sPG{;i$=+G^O^pz+vovbG3MK`Q6|UmgkjQMG2GkjoGB~%2$rQE z<8K8gvIJqq+PulhM$A-&l(CoWbb|kCNP5d5e3n^>`s06eF5y8V!rCp`U%S5#>IBk6 z2^WH!M^B8;cp7kA$KLl~DrA-MoJOvjZeKG;&jRX+B5>F|o3FUx|3p=E?(zaqiR+ix zf2<;9;#@{(Hv7Oaq>3D|FfO}v`#VSOZ{r8%Pu~lwZ;b-@!M(%kr~=@0IpQw;kVE_6 zMSX^cOABX-k6^^;vu&6oD#P#w(hX=F49hHR5?1d0ih;UIRA?UF>#_F}UpcZ1ce+!4 z0t0>A?}%IUBce{KxKoB*$ZpLwU4!PD-keTF+%hm(t=J z!mRS0fs@a`MpMI)?^gG$1W?}QLUm@XAVS%C+S#$n*DgNEPGu=~a(uJ|fEA&N@t=em zCbi%DYh$##y1(U&7HL4oxfB(NE)CI$ZG}MUvEcYAIZk)W8ueh?%yzJ+#2~M+$th28 z#vpuB&{)78v11ElAK8DrVVW9qSs={DNF4`VF`(L4QtrGRos;A=oVg8&8bI{Dm5NC& zoP0Jz!aE||kaXn%F0gZSU8p1j(XMI7FHRDghtWxmfVD+8a({3F3?*f3OMM0$N19)VuRP*6GIY^ z182ZfiyzP3z1L9$J%hE8Slttt)~P=RJo7W!GH2F?O4%hiIJC*QJpn<7sT111oLg-fcb5eKzL@;1+5b}*oAJIq z0G#^!=8#9j%y-iH< z<8uq5dZQSX-}~V)JM@-pVNvDI?H>bq+<`8)Vp()yxS~X;xr!U0L$0dLyI|dtd$0)S zNj%$PpDXRi6>g>i56uotJX4qXo@TN{E|`6pnWmpChg-r`HG4)@;+&$&sDACRUHZZ{ z;=$CKLhYbVtT%dasG?rQq8v3QKX)(yLx@SEl|d8m^>1R*<=4+#JU=qh{NE=%1t41a zJ;>TLRDAtgo_eft86jR93?@x`Rft);W`lQu^?r6_)fD>>2#AghFNjpx1M8G-V(-)6>>=cQ=%o}pEohYJ!9}l+ zJp+tW|DWNb&x$n?#~OgEz3@}L*jn2PY-cjxemwOJ(DX-mQC3t#wYww&Z*1(wODrzj9~?Lq+q-A{6-M zJUyF_-yukh=g)A{`*(CBa-D{Aq|4Ai#a#rvxDb?cXitrZC17XQZIaP@zS~8-h^0>U z!eY{#X3wasRQ|k)i4OIn_$%N0|H-DB)s=|W_147pCASMP)BWO6hR*~dRRJaSc~_fz zsF3VLkOkJaw=TKm3G z-)b9$a@CjjzNan7kdC!w>Hw?2IGqJZT$24o)|=A0EeAW-6AFZ|Rmd*S!7htbeByHe zY56#2zc%yX@i^Kl*QuM_GLWp}7)CHFhZ(hx#CxnOQatM11t>oH3k*!_;~p^{72tBe zCp_IIwo(XhZSr1DS`7az-JitwCL2PGs-n-_nR@j|K6Y)JRhQrKWsz`MP~4MFCwqyv z+#{}yzYb?S|3;eZhc!wg7Ur(waW1$k+Ng|%JkDNuN)lQU98Z(7^&^V64m=^NK)SRn zub@7m(L&pyv1L767&W-(2&HSq$`wQk`Pqx}Eiz4vI=d-4^Oh68N*JD| ziIsqQh)rj*FH-O$*3=Yj8VyTO;QGq6Jh|@%s)Hq%AS}j8lNGUB*9k*1Uo=l5L+X*C zA?oFh)Zbn2m@MOSmC{?=eF22XSA-digV|@;=qCi!aqm+$WY*4v?7%%}6I4*o8%&MUYTMD+p1TOWnsFp}P%7 z9jS~L&_$W*pYGl$Ftzxn$H7~Y)f}NZUrS@R#7|@$BZs5Y+avc}#Nsy&&KChyBj}2{ zxxUqf_JXy#6}yD?FZOxr8C0V&va-}|f{E0)F#H=;?zdxj*1cdZP_R6I1F>s%=Uizm zfg;>)BGCL7*y zS#)49?L@yfmptpINbbsG%Zwk{Y9-Ycqw${G+B=?gPaRWi7<=uv=X+c9>ki&^@?b12 zGJ5>Q{`G!@*wzqK)l2@X0ANS*!s(Ie{y%x)@1D3YBm_fZn>**yFXkVgLbyRzAe+<^ z%v5mVs86hUK|2|j#py0x@p!IlS#5iH*y@ROdF?=kJn$dZ0{o*S5|@s~rIQGJn*pxS zEIGfWP>JYRt>G%*x}SWj`$=U*ZC7U@JhBR74X2ew^`m5MgAMZoQEsvyk@{ZI+p_9o z>dkrwNq9>ldoyO#SO0FcG&3Nv7n+;B1^*|7;OPIP5O8x07np@r+;M`A^RmuoNMwFO zjCbLD|8C3NU>Lro3*0i<(1~}`AJRYJHmK~^_ZPD4VQugGTz>v%QDMeI1xrx_Ps7fg zb4w{19y4Z!OxX!*|6z|X;<%n9sP}37UtXj*>pg3jJ$QrcT0||ykD5s+Fhk8wiANs9 zbeA(?7dq-N9~9n%2lfvPNt)jFca;gl7r)bq^VJCE=oqPlN;I^UettSK=J@`g?j3Eu z@2IDR`aFMOK@RoXmZ5(dRnR|0z^0kTyMKS;-x+{(7FHKK%y5c`-pP5W-Vm&5qMV)Z zyJ7kYjWj|JkgDL7SvYM_c9R`qL1#qOwOu>#K7qOI@ruL2tnc+=v%b(MzrrdzX9SlE(w>P2Y1^{C#{04Z+E5vKH1H=zlB*3GTwN?0A`x|oP+pw?&(-X61actQqJWi zZi#24RsjY_k@d42Xi}z#3?IlO@3L>)cHVE+WhyY5-pdSRL{&jTh=|xr0`Q$-n7IBcrb43A|NS~RQ-5l; z^XBfGf5Jj5fwq<2KZussYSB(v_XqH7eh!Njqkk1;E>52JbE{4xh5=-aDuN@alg5mu2{=;GB=IJHukG|H{O1#`HJ9>wO=os|He_ z+lzN_ct>FAKcrR;q>Kjb{72>9Me$4GeE)qnvS@@LIY-o?!IBZZT{#zy>iogxHs6gD zlBO(iitzeRynjQL@OiGo=b^a&YWgpb^-rY=zHF&_(qb1dtaA6a;qr^OnqGRoR>1$8 z;QATalZ#&gdkb{Yl$+?Aa|kSYYKJqnG?xn?tj#Ts>#F!;<#r z(0SC8U~+EtM%}l6b#{Nh9VRT$B}xJ6f3h|)uxjyA@584bw^p4)lCT#(g%ZSn4n-{@ zD7lXd5L6B!<-caP{6;xdOJJr5s_`FJ*()uG3#6G+{nY>2pK!=;N+FiTQs9(;z1$4m z7%}V?$W#QfuJajSUfByuys-?_ui{o9WX?y{10`@Depxj zjsx(-)&AR6@vrEEX9!u=_zs5qKepW|%sI|iccCp-wG4R)Y$MJL1ASof^?tg?GEoWh z{u=laj{tlgK*(tOF9x7*rjleO;A=+BZ~j2xlG9scE(~IIBs6kz4N!#`ev3EMP5=jL z!wB-jaC}d#>w8F+j~EZ{Z!b{n9;bdr8Sub3Y_n01jSv;!SpdFfy1!TiA~rOlgM^-8 zA@H-Gq_`=Z@)k#QSoL@y4D!!;sPT`L?lOR#0vaTXrx_Uk{W`A@aSmzTz5Xlzcq!3M z4)3?P=BiOVUm@eCbdpBqWg~7uUw!Y{md~Z-#pM7K)B*+#-a_ZwznSFj0#lxb#I^JOD4tqcCv&8d5RtNB!gAO`J)Z%%NHo#?t+gkYZhMKt+l6^=0e6 zTVO<-p%M4om*gCg3za|M6P_R^)&jcelTX(P{sooU{PnQ1S^nub1-F9yJx-uen42IO6BO6toUw;ZYZ|6#%*WCjZA#VF%Y z`-7zK?QrxS_kOHCId&JS0wb)nqpOG)iNFa!30!Kr5ah2;l8(zh#4haqDj0pN5Bx90 z&Iu}mX;Uc>ej7c`j~e)Vgj#J}2IC5U&I2vmgBV?x6JT*V1KXv7`V`rG^~6h# z#nkZIcoqFXxJFHVdoAd`Z7oyCGSY z1k={3$$xx&Rzy(eYt|n5kH0}Y!%bBNmy;aw^w6~D#eG{DsrujuzcP7!WsSg`@FM>= z#33gmID7o&65Odd=pBgLDu&5Gqw>31z&x~Di)a4v1m?iF~dqHuK#*1(z zXDq>!C_;vnvoB@vlUp z5q0;%GiMup+V*GLh~OMh>_XDp!e0T{jF`+}J^bhfD6x%7G(T=@=Ci#hUgMz|sOJ&m zG1+cpIO+kccQz1>oO{(Z2jBo$13H-|^&?xmpb?RK?oVn10E-AilBPcsE`ke(R|vB zD+9_)t)#RgVG`R~eb9%T&8Z&^NJE^rs-J?dk4N5YWxCW1y z{RCy!#AS*7*_7gnh8X~IhOVEz)MFIm6(H@-Oz-XNIA?n0(7fGA(T(&Ui%R5ui}YJY z0++Y*2c_Fuf%N<+^Nk;#C2*~f=4mgF>-o=5RV6>>h3VAsVtMk?8#y+Ds zAsi^zka#fD2}91zmH|kH7c_b-x^N1C;XZ#s$DE;LHaVzVCAyM&@($JY&EL%qXdt-X zS%u#GY^c=n?gfL$wPX(<8oKAUxf&w9^D2dz>34=BK(*Ahfp+G|0v~PSUMM+J$1#NZ zs#C52eVz{+aBW#0EXj=l*FJZk*i^chRtgqeA{=YbDjLvu9)ep4wnf_hrH=3}j+K|a zbKS_BG6nr=E+#qY6j*t$Hr(doxg*g8c1LAx^N(0NmH}ek`4&23TR-h;aRT7hkiN^v zoTTM?TPSSqat2awd3t0?+00-`eMCQqzx>z2eZYCttNKp5;_j6+S2<~{|NbO8z>?JPdq^w0bqx5*bejf+*P}ab34rbTEFHN zu!I=``hG9FuItxEYG<&@^U!CzPj~e>(x{i%n+iW>8EFM9t!Yr^T$%0fRbOY9iY zigA*3%;T{e6;Dr&y%LUOcTbw6jypY%w)$*Z1^PBe+EEFTHxeaCUrAS#JuV>eDx4`# zt^D^s{DAvsIlHcW-2Lxb!n!7UK)863BOwEvJNve$OsOTRNjJBp`Vf zVk1*&HV3reqJGU;1%W@CkhnDrXxI!LVHXYBa!V)hs;RCYkSJXxK1XsuJ$?dt)}n+i z&<+FzmAe{YOx&>kv4jp&~>4d+>jQBdo{$_tF|ik8uk#^*E(@UTG_K&777H)A2&|1#moOXbe)!TBFH_moDg9^TN<@^FHW6UpSCS+DJIwWGU&n zt2DhmiA`nu4fF+efXP{8)x^}`6v9mi*rg3z1IMoQ6V(U9D~H<JlKZp$ z9zSA5x)GZrFGEQN_ss{DrjzeI-U!pq~zA2V<522_k6V=Fg3vT)BlbC6kx(dzN|z?q>qpdgu12%Fpi*7h<27P}x*32eaPW_wiDdmHYLDH!rKR-$mi+c^ewj*XbL zXQ67k%$Q4Y&#=&~S7IYpQ>yw{rd9v7XzYsgnO@~s=!mNV4OjjZg*bTrjAhJB#p*uB&rCzQW!_Dn~9lyvgT-L z#6p8U)1l6vu;fwE?p5_f6z%uG;C-1YMJu5Z*A&Fu)6=f2ABK=32M$pH*}OO>7!Yz7 zb4lwey1xzgX5z43jW(_n+Rf?iwp`*kt_MVh9N@w^wTwfB=>%47xAYj&Z1~cAf~4a} z(|3wL{9FsNMZHt|eF&{8Xjz>g`VWxqf*eN=%FEAE_Ag@Zcnlg|&r}{Xe9x{>bRF^; zH0#+9GXGjwxkP*1o;c|WGJ9v%Gx8oN(?OM}*6m9!L!C8d*M+R5_^x#ZTZb2fHJXvk-)@g8f&-TY;*pNm(ZT46Gd_1^ zUIpAj9&wWoa0~A--LE-w8Mz{pkSnr=J?*NQ+!)+c6$oGdXaMp^p*~=n1h)-oeWZf0 z3`CxI-3Q*-Ll|diUbTpOW+C%KARzRipo$137n^U5N_Xy75!$QlY$}SlInPOldOs3K z%2JLLDreZ`__AO{sdHSgfV!nXchZz{+u)Cp0OfCDe1n$&b&Dc z_nssbM^0%nlFm9Rl8n;4j6Qzz`=CeXocToBcTZs_88S7j`PfrCZHR?s ze)%-eFK9B2zrSRvDIoWBVy=OZ7|(e=$K}grE+TG2qP1vjp_}~SGdf$j_nA*-`5BY|&IZ3^^gwWy-$H8Xk@mGv6r2nB0v)m*Pfy)&`>V97-u{BUR z9WgJiI87+t0e%0`EAR9s48W?anj>3!5OM^}FOZK-By+myUa;o)nih?TI@9H~Q!(o1 zeFO>QUHn+24)Sk$T;E^4+rX_8kOo1o?ACnEncvwD1M+B}u}3Ig(B^yy?C4`XU}Rgc zKb!zSdFm{Yh3U+Q}^X7U&NZyf#-s$TOXW2Wf}<2UBn zf%GpgflIHMsU*L#Iu?oM((fN#n3pY4*O>K(uI69@ErxWq8;4mhjr;9#2;UCj*c=TD za1TF5+&z)}IEdBC;*Cw0Ko{fJ{nydb?&i98&5CbfApA5JxIXv#f&Zot7uM|1`+6b& z(#;=y?ZP9xjKK$x5P4|TKX2ix$kK)7Jd$G$R3as|^v5Y=tT~vw zcUz>v-V@=|ZG@}oV)yt}Vo{#GUW)Ae{d_!py%i7bq>X5+9D8IiHK)=sUn`|X&}qxr zCZI3OM{S0VADS1m3UaVJ0Rt(c?sX_t<`=H~dXnvX2@n!YNFWPRekQ8-?_)2G_5HG% z5ayCm!@#dgg9g^Tvo;sb-+oU&D9NcTAT}$zN{5LkYi6FZ2Yf&}F3P>zw%ZFa}lp zX_L)TQj)pt^GgE1nE`SQt)ySwSy&gCYuwkvq>lTmb%Ae~q7R!CpDvY%6X!B+A@2Ql z5BuYF2*L-I>x(U=Ey+P#I)&+F*jemHHwWe4as0Lyrx@RmOoSe=mv~C#$l3e2xyj_- zKX7g)#!*?u-TdDjV1(P_D_ucpFIc;Xc<;TJj?tS81E5`otV`l10R6p!Qw1$u9c29*+yoA(?;M66jo;zO6Jsx{z&weGG9DX!@cIK-c`kh0ssV=S{bLjOUzi*svS|dcf z7|tN|6Rl^m2yv*p*8+O7m4$PM2)N=ZoCV4_jp~GV0#~c3qOs5n=R7IABOzn5`Slu7 zhAW;&>=DvTxP{=Ge6Oj7t1(e{XG}O8hLYTxE}14xxT^sIT$jxovnRc8#=o|Rt0Gj~ zo!sQPIE40Z8M=c)#v}6SR;FPYuo}xFKd*GZ zS-Hp{9bK;F_}+37MnMjCHJaazlT46~!KoJ_ZxlTD_IK15@JRES@q{;zjCqm@!0QHuz6@WZ%>F9LR9u7~#5Hxcjhz%FlhXUC#RJfl^N z>$nj0xC|53)>>xzBWk=U@c|QLo9Q%gBXBg`<^5MRgj6?dSe6Ef`oY4~r+Wh74ZI0(7`U&SsB+Pb_hpIgk4hp297038VoctzZTbm!+3Y>(E|i@JD$s+sm}x9SHBTY#^=7G3V-fdBXmr>tc{H z=F&wDqAMRwai&Pk`;-}jlyN2{z?mUL3h(QqHq19V_7%yNDuZ9xU z)Zo=$``;^@$a@jDr%<{=%U+PXln9rp?Y7PrN%#6@GdZ7N3d=|vK3(hlhRT~%-1kib zBB@vhTqi?N;U`(e(lOzA^}i4<2BKIPDqD-@b6tHdg6pq&@pP3miCaP8nG-5Wj zK9F|$`O{7mPfre%cFI$iA$NSx&1l&V2Zk!ekvdU*T6D=%uD@wq z*j3lmpN3x24Z{TPs?DzFo#FD4MYl;^zJ7atO3^7z%Uf`XVC%u_8y9emRF7Yll)vXQ z+drlJ{bmd|nyL1};F-%GFT1HGS*7YY<@Y$GT^+w?DW=(0m8>%@6LYh?tC&#ngQ9q0 z=d{77;@ZYlg~LN~D==!=S~}Brn;|zO;)40RZfA-ZRbSh`3cvjfdt_#@VRqPkrgC|Y zOJ>3ryWI)LQwKqn1;)MQGDq%cHFORClDW>Bp&l9!mGZRy=+j&0&uT-y+m26t^k*+K z%tbk1p@*t1nv~`U{pT36fAL=)vKe*D{Z^HtHlVv(n2?&V5!uzm*h-^$Yb1y*!Q7xU zY|UD8?g_T>LKu0ukU}@vF*9w>*Sn=YYnMG)ypGKYUkWS;-Th^;uMk0Ie(&j=*oQLa zpjJ)ZaYINzUEp#*kQE$$e6Iw;S*mE|-L2DS^n@%%RZ~$Z8@PoJ!#=QW+~T8jfK$HSRLfyes*7hI)6U^C{x^4N}g9L(|G@ zk=JTSLhe=HNc{P`a+86|&9X|eM`=IfN{6X$AaDU!j=!|I`24)8-sb5EH0vLO36lmJ zU}V29B^G(zR(vlXvmW{yK^L*i82gV@GUa}t<_%$VZ41S@HO_%4hK|Ku;OYkwB-0iu zLd+Xo(&XO*$na3&O|K+T?yE?T#_wcVv)*PG*Bg%Pz|C_fe5ttKD5%G%tJJY_vkTbz z7cBO(EIyOF83{xpP$#jAUV=S9oy&lDu63dggA7ZTiU-^5TM>1_m#o=Ug0P&IrY=fgbf-{~%iaTe70WMMxOX}|yYBmE<%Yg%4wb@Z z+@X>b*UZ(9m?}$q;=gp9Y1okFyI+G<4ksV|@$1AQsPa~J9OBe=k_FA$Xj}}!U*RqE zK33`APN8cPkk$T7mya=B4MTzp*PmIe@rt~$dV%Y{IXoHsndi20<0GPk)!*qh1ihmz zN*BE(6hSi5dp<_znbEDQyyq>849u{=LL=taxu;LSK7nSGH~tPlC*&o)8oGN|^6LuK zM*2>~*&b_jZv^9FmD>EW&5-KPsaT5KU~RBPb7^e20jl94!hrRQrqF~VEAP3gZ7eIz zmzBfCB=^m6{|cy#-puM~C6&{8p@Ij``gG${%FcG2x!WEk-CA`mVbym5+e=R@ z02L6lX~${(xtaNRSD05*(%V_*OGEK+VK||HM4gdUPEn+79|_Uk4zVHs^jT^V%lj%% z8dYz(YYZ05f7GR$f}PaHZY8Qpg>~E9@?NPQuiUH31*K~vC0#ZTHYw&Pd3^IWRGE){ifxt(vwk=XMd7e{vC zn`+HpLGL7|5Ks%~Jn_bjjz6Fxn_Ka_kDXlZ(SzhVML=_J-N-g+~ z?}g&*Kq9>sGgr~1qLsKf{*{k*$D%@rRA@S^AX4~_xWN)a+N2X&X#;FwVnKpqTJ0q3 z+e`3B0B`8m>u5Op%S9rtPVCdG9fhr1}2!PqJ{#s0`hjLy?G9%D>F;`0pM zyy)}m`!_3NLJK@Fm-s!jKZHwS?_Bv(_s;D6_mBu>3({JbK5?eoFw%&{xA}ca^gg*_ zV*y(kevF~4jRvJP&^(CLle>JH@wW z@=RoT+VPWp2|3`jYyzX5lSDkL$?v_nD}V4LK1wdr$u;Y&oGroWA^8ovGC{Jz8R04M z@xw*H9#(At>=}}FdrNpaLHP?BqMa_mbCUDCQzq~9BdM`MXgNwq zK05?wm5UYaf(8!FS41%6SUXJVcYo^IZW&?YQ+u7K7W{#Ky$-b<_tiR7<=UASVIsex zhTOtyZqp^u@eVjK)@O@AevD2l(OLhsGnYj_(@XIKA{pnmrY_% zWEi{qb}1m6_~io}sns4z0Uu%zeYD_OryP7T7C%cbgL4**YZm|Ann(P})oNmz*OH_S zJg+_Tlg4tlF}On$^cSDhJIlfb#VAl zoCT@vytXcqPW!C!_MdA>Cwj@VIXIWXDE^ZAt-@mma5|q7xAa>>yPVlBy%4k|>7P!< zYZXh}2b!1_=t0KDKESXY?UZC^#O`XX@4QUSYve}>28Ybe7te6* zmEL>}i!gIFzz^B5lU#gz@3w{0rTi*2{jdu8m)SwFEC~_1ZPSI0A4WKc>=50V2!pcT zF>4qkqCXh=1v%^2{ko~55sy2e~gul5oRx4Iek;X|dYz)mY0L^e!8D;&Me8O0i@dPS8`yk%SZIsg$S!B5V^Oe2_qb+3 z7ey8t#cEk8D>9cFe)ucZU12jy{xI%$t+t<`zgdNP?~WGQM}N4uvN@}{VZhxSC4J%c zw!&<4#i)m~eD_q9(FkGJ$y4Zmk)&MC@r-8f?wG+}0(sQtZQB0ENBP39xmP-G1Bv;m z7S!$0`x{MucXnOM!TjW$%96DMo$o;nw9?*_w)ipbU3h(T_##kf6D6BMXI498SK;|_ zMb3~lT4CFfE?<)D$a7!E-o#HW`WR=WpY5ZtZnomklLy_73Y+o76hDjY+oe;#donbe zx6I8nMqunP#a{1!RAElDIZoUoe_-Y_>2=3?&yMEEWu9!}UVW9l-|qXFI`EySXs}t< zuk>#y)x5zXXg8df9HOFTZok?tMO4Q}MgRSMAQ716%3Z^1Q#`V6J2+r&Vq?Y%6;pjo zy@Eg6{b2Jz#ITExz)lNA^tTs)iIZ!0eSN7FxfjkS;PpVMH;~ENw<_87r!)RC(6RD-p`bJG&<5d2{(VM-txq`*SvrI zDCv9*FD~P=~Bj*uHFrjCb89IzAWt;R3jE*fAz%)4h9jak?Ysmy7yEg&Zs;wGV|`0>qPzm znC&_NDQlK~C2Yahwf19Nt2d;3>e*tG|*M99W87|*Yh zvPhb^GrXodY6TVm_dEIZ&>0gf;s9(dk%r3r8!T3gMrmHxw9n~gHdAw$_)|U;T?bam z%(gG4!kLH!i}l+93_tQjgEg-k%ZgAgcwnNwpRvar$>g0syA||!OoejAYW&D&(=UD& z+FuiRX9_-5Of}4NSbWGavKE7utuDcnf}==g)%hvkBap$c$LMIWo@p@VG2&c*X?A1c z$LqLs%+Plbp|dp4w3)PGHtjXzr^ zPu2g?hKa!ENHAZ# z=fX4bt9)WVg;uS^no(|ODwapT=V6W++BF9?FE;mNA-lw3uDRsm9WJ%iD_1${b9-db zH1k)T;&xRI8y@1EtWHo~bYlveA~$}Hu@$}FTBJhrQ_|t&#uP1{>33qJ3f#!~+J6L9 zN)S2qMAbU5SvK~PpGr$z{~7(Km#SNkJI$H(#Q3=cnpC3zieHbBpviSv>gFjfE92Re zH5%!s5mr%xe(qvRc%-;56QOs=q09HU(^fyuE~v zgwT#?v*0h+P`o?%1-EbtW!LyPmdARdyx5lnkBG#i!mrFJ8R5{omE4kQj^_g?!joiw z$u&k`l2-XCX@PicxFm_E+j8KLJ8PY6jQE;^Dn6$&lP5LWYx(S^h53RkG3Sm|96yG|lrPW?ALFSs z+Sgp`w@=~~9}AP3I>YQCZ|@!2F%Dw)o4HreCB)jwac3(lI5kr(*QB^yegy!FCSzR9vPs;1V;*Jh)_(U@A4mzD0{!@0kd z`uf@nk(p;w@)r@GfD7S|#%p~n<~bX;RQA)m#dnkwj^%A+PH$QFq<3b^O?|*Cw9t(5 zG3vYIF_&;>g-vMRWqYXJ2TNDr&Eu|;vG*7$sy7n&ET`fW*(mptR_=de<%^&DR-y9i z1!vzydH08;@*LVy55(NJKYnQ)D>o*=S`y?a{#9T!IIEV}D)Nn`@0v%cWP0ED6v0T# zs$^sEwH6`Vv>vPeiN23G{Gv!mt2)Da@;^KdluBX_grbfOnbyj{)w^he%@TqBCsI-d z7hQ3`UT4Le!}WPyzNt`D z{R(L^(v=lA-}xQgKJyDV*5n4Bzv_a+ryLuYNdEO1l|clNxiLXh*9p%W#~=~&M8kLS zpw1cTsK}qfp~AfN9`)pANz&8|ILXiQY+vlY<6)+ee)YgpZNm6ecqy^=m^Z#R{plQ2 z0)x6!7y2P_TJi$$bYQtMp@Y9{Yc=?= zF1iK@az6>URqK!;M-!V#<}G--CxGk|K4tBNN*+HyY3h|0<{x7fxKAjrHtN!yq1g3l zJXPVgD6d@4C*SkHh7_A<`r0?TBFKOdV;B43hXK@-9`ZvE(s2pd?s1jq@BTZ$bXgV$Ck`7Yj-+} z*t!`e>vxfII`0lPmH1rV9K#&rjr1nL2|qEnTH&*pSOu22g`8fJ-8~IF9-HnW(|R_) zOT+DOMP6}#`y(}H!7{(Y`~+0tX-boTo47439r97KgGR}oa*P3avXh>tF*(|*l3#e`saqn>+d{TslvIG-`=cHIJiyy z@WKe4Ica*|Pe~HL;)vopVL6rutBbY<7l_YKOm|(S8+905M&_pE(tIrw1b%4=^uh-% z91~poiWI4bUX-=B=pZz&HZi8)W~a|+7U@w;@AR#so4kyoa>0e5ZQ9NTMR!(@=`_w#+b3}RG(YV2sp_v%sVyc^c8iT|0ZHKwxTnc^Zm6gJ!hjcF`Qv z+zPX{sC_U4dB2g|>Tb?_QClBzr5To|M)gdPB?-TEf8d(S`O!m*;d}h(EVX~T%jIX} zMy~MrrSpw%sO|<|!YdRJYPS)m^X)Sbw!r9=+-bIx zYPzD$+QCfFeoma)Z!7Y1@{h#K$`DJ*gBUOLsnKvc(a%J;<&x-FDlfb%W%9XMeBw`gNRw-h6VpcnfMiQ;}u1$Ol9wU<3389Q#1 zJm(E)ljgZV{)yp~sTxTTUg}X}+SAQXlw;GR?WUV1b=Ph1DRwN32+s6Qp82`<%I_47 zY~^=6R@0=?Xk)5pp)oz*=*4Q!of#m$&UjNOQ;w!y{iU=R*~+%fI@UL7Pu2%{{MQs~ z#IMk~j(LmNJ|Z~Y@V~N_w#?x1bz=VE#XHuL-h$5+D-7vt^1kvutxY&#AgWm?!o?=a zk5Z#&?~ot6L>@qN&Irp`nofe<0JojuDAdI^$K>kV#Q@syUqZCsv$+_eu4i4EiF1S* zm?B>Z*ZeS1QS=?tq7Q0WW!BVsjOV2JA49`Cfi}~4h3}&U;f4e>< z`B1)ELNtk+EcfoO&4n&4tv1EvzEoGDn@n#T(}SQ>OSnG~|U?64qtz^=g#!!ht_mf}m{bou!9LuFx+pA?Tmu~eD zHrm`|BDK4fzlv@Z3S=fT2PS(<-@@#k9hRI#n(bM>`H#JGaA7&*jGJHF)Wy0O@vQ2F zkpRK_|7FhwNN+>8vn}3DKkl`65LmSKayK`-7}zidT)$fT+12%FFm>vuOy$TZt$a4( z*z=^`&hj-_E=gxwog*9W4>aG}ea+5`2NXQG_g%xTare8Ln0CZ|crqzh_;8~1U3B8h z$shOBDg9PlRqBjcCJ3=i0gnheqj-2Jo+4^i<+!sCep$*TIZRJ z647#`1h=~qGJJe7rNws`Zt>tZ^akj*l4gK&E7g$DSC3h?auR#H_`6u>$)>P&w}cz! zBqcu{NBQ6V;$Lejw|TYtl8)9FhIc&5z*T$rJW!K}lOZ)2kM$}omQ3-K0PW8?E8~a5 z#&(y&O6~2(T0_)rcq(_tQ9{|{?}J4HU*E1QW4OlN(5>ToTl~YCxHrT1S~1&LUbO(6 z#;auJ{>er;t?6dB#F%5jbK$blZU-K2VO^f$sBG>RAfgvgi#|5zGMB(9Y+;*O6=nT^ z96gK&Xns=4bD%&dIh{nYug4(w1zLBLaUJzGd-KdAbHv3D0u-$k-M#!Vmr}O_-TRN+=x0ygbB(x> z>&2#2I!B?ledA?C=4U=fVQTzM$HJ;R^#Uo)vRpe(!Dd)iDZ6nRhYJ0dWv9$CPmPhI z(YdLsol9{3+*lrjE6&Mw_6n+L3Cp`(itla{|&~Jd!K7yOEIUDkHfWHW}Y7 zEV$XGM28xy@s|AV@SSCoD9p@_rXkhSONqps@BK4H?0!q2Sf0n#c(+dd;_0STRG!bc zH+tl&KeS*+{K6ey)OjY<#Y=4T#;j6)fj`bWJl^n677NYbCr~W3+9e0CIo1SH0U- zNnz@qGF*e0sGQE!-r8E{0Nmi>G z)pt%TLw}#Sk{fy^pYgD@=0Fw*lMc3LE~Q|kbO2C4hqi1 zgdCx($F;94M+|2uczy72!ccBAg?kU)TZ@N~8{_a1eO_0n4)#_)Ch8d2gA^oOyi(_) zOwzR%yFN`a-p-%wiB#Euj?Jxc{4hEom$L32MSRBtf1FGCbx&jDut)jV>fB4UAr7Pt z%ZcHLD%U?i;-G33j8HeZO+XBEP}3+ae(}f^g5b$%%AlA2M~&hq=}kCqi9Dh@XB6!G zcjU0tdr%t=rVsHv{hZjF-G%M*ZV@K4cX|5)-`utBOR80HF%HJHMu8tiG&(>4uoydT zbMiHFs+Yr2EB*O{k7-Sw3c2rk9DbEL43^zpAZ-;3zhB= zQ;o0V7OwSwbH^sYaO%oXE6ncEw=#Zz`4K4veA6$&MCzTtUM&L`1)adxTCJ8CHzktb zTB|7P+9wn?oTRyzrxGaU(*M)1&+-%I63>^rgEsX80foHGGd>0u+}1jsMmpW!F9eLR zwHQ@KH%?be*cP~(-yPKcRH>Ax&-MmILAb=a0_L_)&suHsWNNNl8bN3K!&=};5}oX`EF=1JMOk<0*Vms zh14c1_cxu@X-hR(2EJRbdR13z;vO-CrMv9HwtVOjP(>xi{?oj`+UXRt$7-;Vd;-G% z*pRBbmVe|ci4U=LbB05=Ej-Oj?)`;ZhL4}ZF3hP)4RlO$abO-D_|65W?6h88=OKXg z|8D>u^a@V-o=&r`asAqQ?b+W{2y+fh!H%om#X!eUKdU5Si)>(wTqoDg#)F8!{@Oy` zyymfVT(1F&Cx--e7xv?)z6vjw!sk|GEWHecWNFea1J@<{L9e3)!-^0=G^>qfCMtkn zZQF9BK?fU05Td*-sEKSq5p#Vu(hzDo$_s-)B_9HuW}zCQ{oP6WWO%!eSO!(Zr+B^@ zW-+YCAcW`s3!=r4<>tjt>XV#N^b<1tPL*P#rjQ4lQFTf`R61sZ-l2RtQkQ0g;*;YY z<5O{8w~Z>Jn0lnAg2~yXA_Ww%p7~;;!|?Q~^l=xB6wi7Hv8c{}&e|I#n)m&y-}7)dV}hy@(`5m1rP{+tkFm24v{P@r<-`cP;beowg^Lx+8Y8(qrc$zeKg%CXrK(I(SH5)YW8k>t%8&Vq4oM8c;YRtY<2SZ!sYn@ zO@od}pC%#2Ir?l~5!lxM_g^R;`9{`Cr^NQ1pa}L)+Iq7yy@+8~ER=f_qxotv4?fwNo_e_Zi zCcYWkw8@4cnd(S8T)T1w3~~hS9-@0Z-19#L>_P@WNLUOnqF-$$FkWH&H6q|uh#;T2 z_A-5`Ei}94ru&nyNZ*aa5Wp=CR|Jy|Lw+yu>uFdUZ`P9y=AFA&C&=T;PtqjPdKd;OV8T$)dTa#1I>GwByXq1$^iI+&M8^sDH66AY)tX)R?W^FloYGTiZvuy9wh$2HDwaS}5R=E$`wah`$%0Ocq{G zuox|Rf!V7tCAd>RRVjW3p-j*qp~QcwR&~mU;2sQd6bw6GTblI?z>xU%IPD{!L_lEF zo!DV;R+tR1@BW)B4MBITRaYQtKI|9R)D<8&&s`ZZO`v-6&suF;%TklmwGQY z_+DAN+{(jH7jBo*S7IlI~iZyhv9T0|hC zjtItLsCnO+@?)naA0BbJ-Yu2>^QWkG^3I@J1V_7` z@pjl&&g`w;@y^Asvug#(4$F^w#&C_Uh6#~g6vnxs1W@kuu&8yw^M!ql&mh6*y@*NG zuRTS_6^I`;H&PLI>RA39&!xcalk!gjljYe;ULR2H8QVXZ6Joq@HdO1fI9V4Nzr6&oSF3ExQWM z22wcNW~<|z4PG9i&mU8z6K2rK@i0rFLexFWcMQvaawyM`822jA-(MBuP+Pp~EyaiC zJv7olWje+R8P9u<*RpoKJf#5ClQ-w@&aF#QCNz;mz~J7*%*+Gdq}k_18W6W)R=cp90avBd-!z3t6T&Isl%IgM$H*INa1 zk`v<$>TB!LrMKwNA`0c}+;mZKYm-%gv$Pkd@aOD)LB3tBD?$pG|XBA!#>=wry zpmv?*?E6ud1t1BhdB=9ra@i}FFeIMl!*EV5ChkuTG;yzW1gjvtnpbhohHpfI8Mf*% z3V}jNJUzqhYl4-Y3!R;EA6m6wau!p=++qjzY4UeY0o_8^N%LMlqD)-KQ{h+7i*Izy z`5a{=AiB|| zR*@f1CHgVXKe(G_xfFPp62I@H&GO7WZWdYI8zud)ILU8!qz_?JQcQAT1v?rM0$!a;SRdgGzIEwTo$2sf; zaWBpn+sL?AVx6@sr?V3Cej_R4hT~8F*powUBd>O#Q#E&y`9Km^x8D)bI=&iM9TtKa zxYuMO+W{EeJ}L%*YG z7{YDKJW(6(KUoHRcAIzf2fp4!HPr^cKBWt$EqI%)GuMpLy=?3)2{l zhT0DXSx-d;8@Hb^%$fF0Es78-{Rm8WrHbF%<}~Y=-knRC1J~y)a((1vnUM*BKmRE} zV6$4RWGV88U~v>1V8;h^6rgD^lYH}=7_DXk*%Ip~(M!j}l8SOnNX|*#qrsJkbAT6f zY0+r2maQUtSf3YKnYIwGZ~+rQOtd}?~ByQ${2J`Db>u>gBuTMU~npm{N$wE znZyaA8-7IC=P2rlP$|p`*L->y-b z_*d@-oQ%4cN<&dU-j<*la67eV7Hdv4kNdh8RE z1Q$C&&;9DXhU~020oA-mvh@*NG2LmmTB{s-xCGGuzJcL_q}sl&JLWke6qJ{sELc!coP-EYnxCtT3+bi zEyd(FvE{#kYcpz_=mm9K@6;h#!ADYz8sW696ER&34kJBr#$syKf#feF2#H^)C2)?Z z9UIbN@Aa`J%Xg+7%%e z+WqV1PO7+3sz!GOmEv^ZIIZepD`P$&E5^k|aV%?P(`-i4XqK&r2mLyq!1Z2V(KJw+^5)61B4bIhD_g$A&8)Y^06-Y}sar;=yx_ z-dX&g{JNJ3t7RUeW2Jm8Gf*v#eJpx@BrGt8fQs%>pcYgAxIpbsy$f`6;fbtw!ek0y z$nagAzLRn)UPnSSWI%6ecn7654Yo=)8XI1&JIQ(lg3zH$Vhtk zWxH8qlylDk!xYYb@Iitys>vN^1b>6!0pNNcf**f;V0i%giV}K8Bn)wGV$l%c#o^ze z*8L$-gTvPyteKCClS5e^8cM<6?!B$t`vqZHc&5%WlTvwj1&frgFD`%*qb(Nmv_vZ= zG6J-aV)e0rp;7s0a&@aQDRRA?hc@B#f-y4EmRbCATY|c-y1l#TJ%e%*ud2`xEmbHv z5zmyBzRyW~%L}N9L8t0dj6d*XT^PQc2-vFL>tVRY`Ru7f=qbviHZ`RLp&l!PGeeNh zMfOp;WQNSs5t!aPaTa4*LlqTLq^r$}h349i!OGyYq~OE(CFHivSCg>^-lQ3nwF8rb z2#k8JpnF?ls^fV*j30eWUQ7%qw}`;6=18KS-Dq!lcbjj~ghB*ILsG%}mB)u?9(r*X zoKmb56Z;tUK0U@M`ZzRm40_w@l5-HUwkSFPXq%PNo&U+ssf|nXb+3OuI*w=3c~a_L zFduMKOz%e{lLX3LKV;I!eN?(?yMfJQ#a$wST|Ac4PEG&XUS#$mJ~2>lYZ8p1hqp=GO0)2^!{W7RZQHE&wENHH z+TV&gJZOhVnWz5#?Q755&si$>Nvq#N-I?L0n2;EfLbV|X?S22mFx9y-yK9CWD4Kpm;UV@sh7qz!`!?TIu_u&(S1nwa-yi z5~xT%u1|V&Zs`)bLTy*AtkCHmuZ>h9QsT*K z**+0G?|nZh&pU4MLHhhwO8?HrLgI=zc+=R`+}g5J_`{Dr5L@YBbwfaLr>dpg=K|k# zt;+&0dA|=gkxD%H_=sZ^cT|ec|3mz)rl$1cq@)e=_PVU(Iwzg#rG34MKl!pl1*o=3v@B3M z`l9IGE03pm7|Z3>Ph;Z<)4lM#ol>oG{s~|`D9`EmhSqR~>m$Jn zdT|JTc?g;6pUTXfF&*C?70CZ`QB6G=ip~`u>Ynfri{ai6+U)GT;w!Cj39z&FZOzmh znwI=g9nBFgIVktx(yPy|5?w6zAQ*awe!QELDnDKDTh6VQLKMA{apD#@YxwvJSWPC{ z0Z}eeebpi}#NE`NoC#0*N2Z9zuE)A!4OY%kiI#m#yu%wnhcIt&1P*GmBnvg3Bw{u> zC~+`34-*K_V;_l^`AzYkMM3V!KscU1pwD396RmN!7va(ne(L9)VO>>u5cX)`_;l>; z4uyPkU5^ZBwz@kaUI@}*$yj=8q%&rpdgDfd-E>vQf!Jge0I59p3_`PCQZME#Hc(#%QGfVp-3N9wG9U4>aG5aT`hp9q~pStq7v%02| z0oK!V{+*MvZc?I=^!Bv*8GH(YXgmD(ooX)Yvu)qh1-ra=3d3(RaBNEle493WLApH< zkh4@B+~&~Mg0rKNBpNrjN`3wK9!9TOp2`P>A#b7fsEc~5ocb0U;b#0Vw`+zR09e?Id`8}_cnaSD8cHkIaQkPl@f_> zAG=RksCBE#^F?alX&vU(^TpS$IDekc5$b!a8x1vz5+0|*cR&4%vF8_@@)>n!G8E%z zuPHEL32T5YNmc%8uOx7tZULPj)h?{)XQWHeXa3CY)u?*F>k2E?gl&K2RxG(;v?_Z^ z{mG%M0Qz)wF6#;F>28jej+AqI zjc`c@smX~4wcRv3@dfojHp=25Ovpj$^YL=(9&IZVMyB%J7j@+HLk(&FZS#G@hA6^3 zCX}0bLhOk%mGTa|uhFsNtAID$pdRg-5Nb%wb&$6H6{gvT!^Eg#@ zRW&PyOy{sS7~L5yeS2-B<1czTz2UkbrHX2@!Ma4y&lo|k&*Un!dZ9J|dg?rJgz2#~ z3@*C}`%m2#i(_aVC!W+`+t?RIssX~;yScSK_f2HG10Ku5H1C6cWBP`YZw}dUt|wj` zf78b>8`OB-Tf9899WR>rj0q7N$cvXz5+8>%1Cnho24MO&kw`+5YVO4jmxX74#W)Ny zEp~?n;><-a5?!G1el;arN&)kZY2)WD%4+hLgjcOwtc28&@mRMAVr0M_O%%60)>R|} zpN5C^9@Z((twz01*r_E}?fBfvr8YKg^+}ZXZ56+X>+2Qc>)-pHhO<%Ue$Y3x9~qlT zT$IQ|vGlNCj_Jln7bl?&E8po=MTm!DU73k)nl3Dpc`K=j=gLZwfI8dW`S}+~Z89O* z0@ZI>9yd$y*Jb&(N1|ISOXFSkA9VT(H9C^Mcnr%4A*V+uopgp*`}xux~#(+?)m%~wQnO6UibFvnZh#41I0fWe zW64BxFakj~H8knkoMtgBEb)y_s6Og)>x9PUXo<*>-Entnq4zS3D7$j9g)@ji=gxGZ z*HlZC8BF2S#!Ky8kM)Opa?bD6P8+e_tWJ`nHN)e+d&Uicw^MWFirzU`LM%>)aQZxx z*K_`lH-2*hym7bqB_`Zo-dG;;*oovuxy>6z#3_D6q3Uu%$)g{6EOX<;Y%%JbIzn8^ zaPsOt@ahf_w7sLaTE&Thd)kfmj3@;KagioPz?CIYKLWn9jvSvuij;ky-e`MEsXayH zwKAsI$b1dP$3-jxRIZ;yw;*y?l|wa^oU6T0aK1%7X@t-M*k}@r&-in=ZBiyU1-L_I zY@3kW6GqARod>dCM%nCv*h_r!<$~NnF6* zy1y*7!0?e|^kK#e8<-WAB5PMuq3UYRrL;Mzi{toR|KvjabBi0`KN*C^y$Md{ctk4A zd{0%RBGT-ou&N1YdI#6MFYAd#&%;6+_Yrq8{jxv-IYJX6^`z44(c)@KhfdTk=R@D_ zk1sDOx(^n&#m?34dAXcjGm0*>NYW|szfmPF@xZs+edhKQaeMW>ORZGAmT{!Ubj_|n zA7ZWYF+X1|rYEHZF8ux+}Giq|12C_dRX4k^co`YP7K&g+Q%Q*)O$M0;c0K3#l^ zsE51O;x4oR&B`*7@sw5FDZaoLJg3;(ci$QKt#!uKswyPfxOz$hTXqA#7XL zd3JA=(^PNC#o|-N%k_w{tQ<;Wd@YS_yxNa~-cRW*m=m(6C+Wxi4f!GiHM$PY2|49n z`!qWFLa3eUdHqx#=AORfz=&kZ;`c%llNTi0(%*RJWkvdUlVIhxWhq)T*d(u==^+U7+xG~EJyPO0kfzGii?l2#}JMl)CT z5no(Zs2!jimFxDI35*CHpW$|YJ@wj$Bg?7B2pz)|uQ6`@@tEm(C%k|>Tey5D^_oM{ z=AW|LpUxRyb$^~ME05pJK*aRbi3+92(%FukA6V79MrT2FSN%;$cB*J!yXFk{gZiJh zFvw$&CWg*-L)qVMOq7)X?kS0!nCUOhJZ+@jM0y7}_)4>w?4Md=$`fMHgx1zD`21k` z*mRerI>_LOn6~f3)1_BTC>hPr&m{TE(`6%&MB3^c;h3FNb7%=$p;+x(5_ zw3lx0`_~>9g#6Ci2McHgUHFF5WjG~@T_-E>hB}v#H2`DLS6BX%s1PlA?{P`l35&}9 ztF)!bv&DFX!YS!BHj}TL#6_iq!s+L3r;n47UhC%AaN@JhO35jjso=OE#;x2}dzU6QZI|!41-^l zbzpCJ|EqhVh!9a5flhlEdtr{md5QB)dtbJr>iQE)imX}oCT=F81^Db=nZ7GdwGm{{ zF1mA_+Glk#7WGo~bH8>?rP4chre3E8x*?lLneFHOX~lXMZe}ySdNPG?M}0YxYlCPR z&wSqJ27bpDU-&JNZ;IJO%`&CI>FQhUwcIChwhMAmLh{qD6M{0FJK|QW0O@)iNG7Ou zb!0o&L-u9ywDt|7aKZX#^#-BJcA>91y4XIJe4oT`7zbLE)f=}M7~`zP2T$3^nlc%? zvUY~a!3cHkuttXex=>6`7R!c?fG$Qa4uZ#!m%U8=XOR+qUPJ1XF0A}1+DCOthQm7L zX=DyJxitcd@C_IGR&A$g-pxS1_5}HnBSx*4r+`P}d_oEw7vCh=|GTu| z3x=vg3J;}Ql#oukI3-f+Ey;6rb<-n~$~(7l z=+%&8bmmk))QT*Db;#oYI;&${8ipaYxpOxDrvMSNG1XRsP-5ZMql6D|P46a&B0&xZP73NOd{gAhvL2QN*`O>qpmvu2PaYl`ZZAY~?@&MthT0zryRJVB zczrL0@aV-%$6viVI!9)~A7Cl_L8Y^tuM8&L3L^MYq>)$tU%2*QQ;B`k-yA)FJPg_6 z`w6heOJ>owEPoaKQ+}~^PTzk`hiu?K|Dd#B{j*6l>zM!gJRF;8_>S?RFT{V*h={Tv z-|^i&`rQCl42!dWS4sltj|lHHc6*urdX5Eh4teTwUIZU5)X{Ps{`&<`1OI-D1|)3e zDu+9C|7-*v@t@E3@}oO?v|ol+L+;^`IeL;PCE|bZuw`Zc^DZXc$cgH%%lLZq=BlyC zy7&S|q-vQEan&D>I6U=7H&3}h+WA*E@$k2supOrxK#_Ejs8D)iS05KTXFa(B#5P4gXo{P(86p@Id@s8{3s>+`VZqU2zB(~@3u z{CdTwqVV=c9N-Vm1c}A|wKSp_21hF|h*`<=>-_#YHRqA+A_PY??XT|ywLT{#d~qWt zICk{%w(unf6cBnx{`)D0e?1-5_G??)%p#Znyf!NM$X)Wkd6WFF&x>O8B4m+$cGH)w zj^6z?(r(}yh4X%!T_yhaEjZe&Ucw^|nxa>7uQLBUeEH`Q#}k{ZD*c~boe76SW3Oc` zS9o-2EDjG11#)Pl)0v6?*-_*N73yE>PQ50U{^!LpVL`sXnlp3JU!MmrDFe&g%S@DV z#4UviMHWU!18En&F=I;q>(i|hze1M@sVt0qG%s+gpX{gGQ*fJgVs3T0ZZk`Wz5Df* zM0XH!;T<-;aizacDQX?6v3GXvzdn29c)xKVb_WM(x!|gwpjZ6s(}24?B1g=gl2>X) zxTJvO5~ur}p-d4_Wt89n-4KPktH>f?UL8T4C{x=kJ*6M0_;eHCvmPVUWbBOz)7JIWRsCH_ASV+!(?rpZA^9G0l0!&T{rRUvU-@_qVhkcVPa$|6bdScioGS@wR=gR}_D}5_113 z5t=(Z97S26P(r>DC30e;q#)twz2uxC`S-y{{B5KKq_1W+%SDDetWxcU?>ybr0)P=>J1sBP>jGP+u<{5SMFNh z1GF^r2;WwhmN{#8ihNWtO)tYg>yL-5KOXiC&A%)%ye-m8=(bK?Df`;&s%qt4Pcm%vSn&DUh|` z+s%1=&rKgv^Li?Ro=v0+p9}eS(CijSf!&m;8#(BUo$o`K&;=e&4TDl)^!%e}6*wX* zIt_~Q3g76hE;H!CobL-ipfoRiOsZS_!_E3Gr}L$sk^;bed1N?0fJN6P7W@6j-`2D@ z60D*{qn`1Rp?_nCd^OU$a9RX%*yJjI-|$1Xa8K^2ffqw!-oxk$TCbFz-;ts`l)P@K zIPC!cXx|;1I$}IDE*{XUG9GVU0L|+XV3zgI$p(IE%f;c3^FZ=u3s*T6u_dHR2raxv z)t)OLXDAZN54jfmrOt*J&jU->Akv$kM;eL1SGVyI(WWk{#%BJWRMLWoI0!@CHPjfG zyAS$+Ohu`wsYRe_Zb_FjqgI3>$;ljH0_IuARgs|FNh`Rba4U575_=gPp1aJFEf4 z>-fscUKidDc^>TTIZC!8lC1|yThwm+4GNyWxd0YF?t|tJG$V!+TxKrm6(R~ILm{7m z?J~*{*u39?3DsLAH~^V}1xLid9aI8RpcHf_cD8v8Kb@9|`+i3Lq2qZ=z7Nk1UI(Iy zp!Waq&EZmT9o{ca-~DY1euo20Nc47}P8H+m+8jpY6YVWjAEuIh)?{o!d< z*kd#pyatBsWnWk>FARE=S3&{2AJ`hBaSZhcW&v_n8M=Mdenz!w3&3zI36-p;X=jiz z9Yn{4r(pX>95|37ZD798o()bd0J?`EkFqs0!)S8#Jl~_>Fq~Yc5&3rDj7gh6ybBz5o%)xdZ{?l(Y!rioyrkhswHxN z3J9lS!%%)6^8Sjw^}cx^s`=uqX+?}OJznilyLtm;>h~u=65VsN2_%xO7kNH9T%Cm@ zlfXm}=GXZTp@P>a;>LuyC@=iiGDIN38@=gew!;m9C>;K1_Y8^Uim_8q|81_we#I2h z7w)?;B|IfO8!IKO-?v_@EM#zP@xyVCZkT2uD1uqmgReclU_AfZyi5s(RjGLx0iq3thJK?z$83ORlvGcHCzY=}zGh%QC~PXFqOg?`}1UWs)W za(65O-oSAOnU3BnPtPJ?=W?PV!FslKs2DIBxC5o12k)-QqAcne-Tg+#4{0AM_&7-O z``rlJ0L(arFtd;KgG9qXu6~W}QePCn+F_rXOK{<{w%`3V)dVmV5yo%N{U`dCM4bcMPbwj= z|LZ@{h=0J0SiiIXXLYEB|NW5Np3`^}m zo9eR#jA%aqiDBwJk@k;z-w2H9+CPC7?<7bkB#J#%7S8`NDXzr3bjMEiWV#Jp|ThpU`U$2JE}- zcjn7-=4=70Z8cOm4>K%Z=knN{I#c)W%Co%l-5H}kFe&@vSc<{Ys1u|npZRTYf5k0c zXOPeU{VL_}&=ScNjn2TSd{QRzp9RMLRa_W(|0aUKs(i_>421C9Z6krj-w{TBQkArr zvL|SSSRH4-w^36ECG4zDk5w4gOCjCBQs5r`w4enha{$~1HR)F?!L@I<>=NQ$q0iO& zcnlI^KT-$2w)!O_eXSK|t4hF;QVu3_`Zgf6Uqf5!nW8(uoww$_0vB4K_yD*m?VTpr zx|YX-iyMed#(G?!)FYw^o-V%6AehzQ#W@!PnWtegb}&qj7|t?~>HVJF&nUiX7$)3> zGq;prX)vdA%>AF}`3)ANAI#o2p8bz-^b3+2kj3Nu&Z45UBQ>e=4-#|mKy2mZ+sA)J z7y+UoNLD6|o$U9V({4h+5#09H*$YqV=y(!MA3&Tj4;Exuj1;s^Hqx%`U2@c5av4Op z;gkgD!uv=)oWWrXK>W18YXLmah@16INh!oEL%DD?Osz?S)`S7FVRkw8z62mpYA`bzB| zaGulgIYLu_h{1R`s-pIW4)(i8=A1!lRn~v9aFPf_GG3^Qqe32$Dfe4d?G=*JQd@sO z%Z6K2k}p*i{(^nX1hPPSjsPP0!ulf7rQlYhqNk}Yvm?w|E;NdOds)d>m zG1C>PzvD4niKF~v?RLuI(7^1x~pBbkIp;dUG-Ae8McHx58>`g3C>WgEGPkYqJH z#;yAdG~_XTP%*dNN!C*m*}AuJh?Yi3`THUN=mi3q7}=q(F-w1;i({;ZNOLHHXQ#h*zV$nz%CiT~LSTQnV%2JvR&D;s1HF|+?n^1$m$#acL4TJ! zd(R);mu|hLlIhe~ie$6Ai%DEmhZN)f*4+=Fm12#E`0TAF0=)T<0v9Q(lpE$0bZH^C z-V(m)L&Olo3fRBhLByP3wk?jx7RCg@#kL@{+56>4+Jj6GYP~+O(5HUKJ|&jhyl^O? zKy(Kp6dTez51%24dU=350AwuT!dN`}R7^cS5zGhjvi7|C)fm+7ptwtEu=%EY9-zBI zuM?doV&-=isy1w95#bw{v)(V;+kpzkK(Wo3tv-Yc)R1Le>$^jU-}`zg#yG(SQFG{r zxviNlsKmmi7z&GccGr*q|cLRgq03ctfD(H zJ1o+uCNW5&ipzi#*|uJ$3MOhuL@Yose5nj(SRj8I&qh>@Dxm9u7dC(-vp-vtd^VO9 z`+r!?_m_w$0ICIJ4)WIxJSn~{fY;4+>3O;*h8BB5dBz$<=9bGEnn<6is7=P%Db1_? zaF4g|vH=TMY+M@(i@FXhrHFH|pGWkU6w-+nr8vS~g(G29Qw*0simmy$3%!uZEnX&> z(>CijWGKh0ekT52v;VCE_zl!BYI}}}#WfxCR`_MD-y>yBt|hp}no&8;jK9PG!y~<> z@ar0D$`ka^*2eSO8NEGy`W(lHIk;=O`R9dEFs@gB4dNeN-{7cwc~T^rwTQb9wNnHn za2>R$@DR|kYj5FLbqmDvg5_>-jMhBtV0|=3g$1(^H254CU=gR1t@n1ic1_&;Ud0xG zlo;;^ox zW}s#t@?41>;%nFUOPc{1&=1JWQdapRd`f|DBbv~jd?(^mft4@&fPd=>&>O9UxI#Eu zp7xWyYPY?<1dL`GT_|7mNm;s9hGF={qf{_*wEToXS z76Mz6Bbz?=dvy=PZxdA{&Y^G3J|Oqw*n~oaErR$b6{52SYV$foE8-4Riu*45KzYVS ziNftGXZ>b=Ej@;5M;6gL+-xuJhZvw3{Rzy#R*PAbvbm4Ts z;`=g+u@gMUFP~#?5`=E+Q7B*A%in0N zwasR^!%PJ9;7BPU9Wc~y>IIUo{#{DY{#E(Zj<9x5*m&Q_W|wEwv>Zqc)$gAmO`GvV z#WAO3g8U#MAB23P{6R6EF6^hGs z8^5J2JbnOJL85Dq^e4SZ(Z7Q?zUacY1ru)rz`#Z7`56jy(@6Fs*zc(e(pn-NMSYyJW$RORjR`i;!lSWqkVJixR7CF~zywf~EsvX0_GN%w>Dyo#oIm z|2)wY+cXa;Li9+6w)@;In!;&wy}0gCcfM@gWZzo6<{OE4JHjRXK^@ zhf(m;Lb;Habd`~jG4}rcM%6*g{pzu)Df-{~tONp}Wh`OLGIi?r-++oRmSn1^21Y)2 zoZy4+xv0=q2!mP4S8?xke&UzIhVP z4alg~0oHtp+@!fbzkL}xL0<>5t3M*~Z)Wm^Ef56ex17A1B=&G%0>B4N$$*^B$hRC2 zNb96niQkzh?r4%sk&94REYf&qU>S)uP-fg5XZlv|XZPn&Dq*cNXU^CT^oTy->W+WU zgNhg}*nZ}xy(Uo%(1>lrya&gPtwW_7PXvu0!hBn1G#Xfktnv4AVfMHT|g*&Z4Ldz z-eqm~{x$+E8BiOZenpZwEW?*Tw@UU)-W&9Oy~@vEb?tyGwljD2NQK@WZ&F<_X>9Pu zS}a<@H1By(+V0vtKMf4$Y# zjIcTPaR$`fWg$x|^(tC>C=fh<{+yQE?Aueo*!1LWBCm-d33pJyJlC5VjZBg!=-(F? z6(K%ahOJc$>{0z`UR*OVoIT#g=;&yg`ItNZsBdqn!vppywL?$;yM!PTFF})u-YfS~ zPrMh=Log{Y&a%zwn188;fmmS>ES6slGr_$pSk#ke+z8+#i+Nk(VFz8cwD{vgAYLAh z5VgDuC_=NyGO$Ae%q~aXcg8JLWLNG5@Tv3StBPvxK!=6;GmK^%l)l=@Qpz3j2jTcM3k*4o9f)0!mFR0)ppBCA$D2h@%eBY`0=dK%F@#VF#=t@PM) z=_z;4JN3bFVQ}DUk>~7C)ey!oBBB0CRAK^b%yTFXHiC%GCD4`5Bjv7I>+dhNc~w#c zEo-s~{vnlv>5jD6GALe*y>ZDV{?J)y(w5u~;)9d7zvffbfNJzTDAzI!=NRgx-=t61 zDR~cOtap`lMULO%R@BBi-<&(7ef2s*t#5A7m4J8q0Rj5c2xj#lk7Jn;VV70k&_FQx z6#6%85(N&f?!vsQ;wQ4Uv+*1nh1Be4zCA-)`%faaXSxT}gnqJ^BGPmjEq#6ME89@P zy}HvTw<2H!(&WU#CxgyjqJ_7PfC57UP_r{4g4F6`yy#SjF-*f&TdW!L(ii(vu%5#+ zk=bYe4&`TQQNgFB56=H_I)^Z@Om-$dY5j3WX&ybQ!l=H2$~s9se_`&@t<=vTy8YT| zY4i$|s}d_q?ZDeDBd*JC1ajUhUi!*Pr?X75#5%oC;K;4bbW&zGk+*sP=l2gNRX=mz zS(lx-+#ebeAJZzj34_E68buIlET`Y@5okrTz}+yTE-0|*Q|m1-H%={J*SfD0i}|ke z0PX>I(VENz_PC(K>{Fy`VxqV3C7@R1HiSKu@YQBHnL4Kgv z8}ZftG?-sTP%-D>Dp)R3JJ!7-UbE1wC^6tNXu{WbyTihSX&0zR8aM>YEM~kbDbgx@ z5aSJoOaV(*qUBbaQj^N10o`m+6Tf0T{DDP(pH$CDtSeia5ozF&5xF`~zH7%hx7x2$ z?(|Mrux0^RA0$ide@2do?D+Y0q$$Q44SikImRNMLtOPYP29zgo#hjbn2h4Ih>| zjgGK&efXX};UC-M&2n@XeS~sn@&4EvC<@HG zd2YjG4O0@YuqFAA&c!Sq+?O*BwjDyaCgz`=i*BFTf$}90?jTgwIxHQ{PeyW|7KC!7 z^CvAHSpF=`Ed9F{&1klhtvPCOgO%=OI=~SBNipNH`EYMGQwnjTOen>rllWBO?J4rH zmz%V>wV8QyH1niA_P30CK$`L5#f#DIJrVgYUc5*F8O7(};TM7G&p-Y095yn;lGum=)#t$*Q1Il$vCtmN9~AgZ0=WPW|k z8;6ZUY~%9nx6wgkE(zwhEiAO+x1su4q|RL>e9Gjf6o!DBR+6^Fu+~Q%iE(Q8%_RP) zhY|=0hzYUPWa?y|-w=0h&e$uldAk;2^@mSZM=^zY$HvAKQ93(HqJ5fSrdG&im_xWV z()2x-p^5@V~#a(Z2%U@l5JJL7X3y8!Ykn(T`D@1dAyz!X7%>I4sq#{`G zH%ZpQq5FF~g5FIrMOOYnIc4(#rbCq#r`?yoJUW@*DQS^!s-Y!O(HnQXcLpYk9UFl` z(rAMJ;JTtBchU;j0=Z|jQum;AcC+w-=A@K@^$s*bB0zLE+POstv{+<*igOu#eF_aI zF|)4BX{;c@oXm*aPBvCnMbL_)pNw}*Ff1(ND8Q@(c%@BVXa>i7HOX$d*PZv3gtklYhZY*Y!+m*LXpY!$iX{qf#8=SHFOG zsKVkl$l}`1s!4pGv0t6K(S}0}>`4Z1p9_-YGOW@b=N9zXEiQ?DRG5d?F^B~gtQ)al zvG4RX|F|NwcW5*gI!>9$Y{z_BqC?`=!;r!^`54-q3I*}D@9)1s{`%QPf_1bxYbq98 zUgcOGMUTBTb)s^6kx22!*fDo)fFvXZ#4eIsqB;P}U8Fkn*Ve7(0p zJ}@5IR5(UmFtmGDd?h=wLk=NtXmfJm9eq%{n5JM`%s3tnW@2f z>$XnKsDmA8YuDv((6N24slXg*K5nZVTL!Mf-&Afv`poQvj$S zL`D=T_UGw+coZWyk@^3-e4-kFyVYNB$G z_!)nifmW-%?@|@$wmJi5pd;D~EwoJ`Rl6Rt z;dT7vJpleBcg6q$#j)*fHc!@@tP7J`1!nx)JJ8*Ty<6m`%za%a_pVsIkRC%huE|f4 zeDOlH2B^u$rojG$4lvNu$8cotcOA=A%j}v6dsJx1Xvu(0%J!i8Yv3@`ZUw z;p8GN-=7JC|8j8x4ieTp=!m zaK_sY@T#{*WJSy1%7NNU)c1^gn^~khQ)8liph-!IW>Hq^8bZ#kpdnHt7h@>|wZHd< z^?2yLF*?Q5CCF9CK&}EcS>zun_OV|Vp~Ub1-$mH}mA>G8d0Oa>ZANc`+iljW9;@bq zD231UECa5kAz3Q;t3}07iB`Vh1$G9vQzqt*A7q6?L&y}F5T>KqfzClA!241ZVy>h% zyvGbG*kVRyMLdg-9b|)e=39=Q9wGpnr#HDJFlUO42E0oq?&4O>9$B7!sb-;D=~j|% zDFURY^~tX5vxF5{^;yJu5C`Z_uC?O7U!emLZ&GJJIbj*Q&!;4an$r>McODXm?|bCnpzq>{HU~yB28Uv%JA=`^S(OT` z&(1o~wkmRO&Wca0zu%Sq5b07V>Z3$Ae`0|ND@DDFKh>h{nT>#C(O2%*eUnfd{ zRSrAw;e6i7KWsZxI0U@{a7~!y_AQxBBWd~>udh(Xmik>dl}RU&gQeqrM_&r{z`Y(w$|K%UBXr>sCa(M)a)31U0)>( zkr4MXtcKC4+OpnfemT6B{Y-0_G}c23Vs`~M`;sJ1n)bX;(RBYB&6!LcItUqfJD3=j z*oUO4&E>oy{-6{FU^|!e*Cz1*~GYQ1W)+{gd6fmxG`OvOYz4-VFhgQV%fiez*CeT%j9Hu zRLH;Xjb`}8F*J+B?;5B6H4O06Vyvj-$^6@#?Bc!99(w^7iYvf4-ahixOn%voJ?LWn zfHa3QFTUmrjArvD-Nl{cu^QAVeKL#m|=l|gjuyZC{eVs9ZipG(5XotYt1*k zH4Ra_-xd&jW_^9hEpOJH&3YX3G>73J;8?f@XOj10V#_$}C&uHfs3G}_WYMGr=xut5 z;7Z9ba_X8@a7}Wc2ATuU_2;F3V)Eh1p&Jgx!N~Wa{Yh!T!dz5f2L3fTF~LajbOy>K&2i@W}v zfb#5Mg*MU$w2Sf^<32anf3UeVCF*&(BN`lT1raHqjELgZXC=w?VC5B zKOyIqE3_K2oQLv9=Knj7L(nS1)%y|8)I8b+u-_BRMgT&2K`&&M=&NPnS{p!^I%=PO zGv#Z(ozx^0F`_xL)!MqO9jZL`Bx@?Nd!aFW5Ahieb6SBRA>2tLv{FHQBx~HLtn;lw zt=mb6LOLxo5CtaPQ@^lajb)N3^2*AaC+_uG-|dTj7Judd z`&5={P9oJ66R56ia!6)+|8Y8NkF4KZfN&k3^*^T0i-3d%MOp15(G8Wge-0=OEk-p1 zDobAuHyrc5smZNt#b&K2FTnQEdG$xQ0ixszbRP1;md6_#;c8n}zj};Kd}YJbUT>}i zyvO+PN1usGXkEn;m`;ScLvgL=v5D*@H;RpaM=zFfZFGbrm> zRoCAsbKvf5oU1JEOKonMv+=VP)eci;j%3$-FUhFb!BK&kzvgKHMdK)>3L-Rr%H;eR zk4+i~btqXiKH^jR1>F8)$pSQf)pp;dojV!&&$1I#BlT@3>nZX-&8ws@Qr|9U&sU4X zGjauBUkar5XanPbIcEbfO9CCsTfvT*Zt~17j+}wjb?ET0A`Zq~J#xqat2-g-qdu;= zdCDXh*&WNgIcPgvhjT!&(L+=M9({NX`W}w6@;k18*zJpT*u{%_ROqk?&yEB2*H+}yX3i3IB#8&DNXX?eKRK_w%MKPy^T@g3S>KL8<-YxT0V zNbMV7e2Yv_dfE`djW-J}ghNDIZ`)&Wi?pH1#?M7mdk>N9CTd42p*521G{rE&oZ_*! z9Xhjskxwb4;B*ODI~G_wc7Ol6KOAs?$*;9*OCviO_V3yyBWw5Y?i9&iYxe|MJNv6w zec$RgiWUHPE(r5(!5vWWw1w#5gqb>7VMdZk*6Rug%1?_~+_^4Mh{PPBl!8HfV(NYo zTmu@A7MY|hahrGDd-;NjEnByu6p8>f>DgMA=)I*Ckg%(euxQ+UD;Y+{B|SPi`hJ!n z4!yT`3%ankN!WClTs-)AxgQLa7No1ryH#aOL*ql{>XRIVE&XPmk)nEV%#JPgEpyL& zgYE1)WfYUan48SE-(G}@m~BsDTw%K4`Wl~vFv>#0{Qt1_-tk!XZ~u5CDv^?u%m!sf z_Lfx2%FGtoD?6Jcl|m$YW@PU@OGWk`r*SHor<3eBjqmYxeeNqh-}|~hzx(_6{nLf( z9PigU#`AbSk5{No7Hv+?&!R}@@1K0J>Rc|%CIblmXTnhNtJ2^QBU!^mWXdky{}?E< zIkYb}v_R@F!`n_QTg9CF_SVy95Y4ooA#(Bldm@qalZA{I4=YaE0S=YA=jC9rB?|y% z#6Rb>tiVKeG1}vhq*Aq}_rNb;JQ=2FX9u;!Xt--0#Nt-5*BGYFdeWt#P~nbJ<*j(} zL7i$=CWJwprF+H9Ev8af(e*`P2S=J$LNpZ$laDE4p^`P{;C}*45L|I zTlc#s2X0$|X}XcmS^wvZczKoJe{_ih2xRch1Lwaj6CMFR2aNvL*IB&3?Gj?48szAI z97H9MwYFM$g+r1!LOgZoxW<<)kVz=!=!hu!j`XM^#ul=k^a#MxFJDnff1B~8^tiVL z67MV#u>5|5)w@c*_d~f3??#5$W3xkht>8t#WBfi}Z9lT-p~#-=c|RvLA#V*By%s0g zwuTR+)@)Xd!Uk$%KF8!t`@ur<072*X6i$WdgD`qdw-d-5lT zJxou(y9c8}Nd9aL?{;#Sb{B)|fq%XoGJ|{qn06ZVy5^4El_R)=48Q^g;7xU_*niIe zJWlxSkA$_=bRnD7a-2mt(y)9by`SNG8q`NYJ@yt} z(g=wB6)-<;tt`0&drduH{%AO|xR|#jyAypQ7);x8M{&l|G+VmKtM^_431@D3z*pB*kYVXq#NQu`CK$$T3=g*(<9(65{hmHfjf&f8{ z5RD!2CNL}<*jv^G&VjTIizvF}@)mEfC<@4N`xj zFv#yYRf;gZS?8MBb2;`5`@EvK&wvJ->qK+J#Bb};?}QQDriwQ-9<}dTTR?I?00K%H z`X-)k_sKWDf4O^ka%Fk zwEy!1V8nJ8_5U>wLr^htw0z%#J4sGH{(E6;BBMu}<4e`vw~TUl!-l`2RhoN>Lr1u+ z=F82DH7F(PY4AYjWV?(T69|M0#)bMpp?Pfy;AFxU+i4u``yygKq9>>KMItGR#c?fwsX zRycBgy*PesFgK|*YIV*bDVnSJw|_?ZAAj;ng(VdU)ff0{@LI5m9lbwk|Ht?3vEKx+6$3^; zPPXrwWLqR0S$k%&KOFft^Z9STHps(6EOnXKvhIGb1Y+auZ5{V`xj$d`4?jIEghdRZ zr4`%-#K~sh10~&`PSO1@wkDYtY|W1=M%KFzu`UDaA$m@Ml<2=%{(XzEXSo}a;VHE6 z^97Nw6@Q3K%rG?=Ok}tM!024DgbeAlv;~ zd?r|rN5vLLw{CU|nPT~1au z6c{)HK)V~EzT~>==nk8EL(T;;Tp0eLqfduyz$}+BBuM^mrZDy>)Qe)GqgfGvvdib; zAtGF~C!`pI+W&M6W}iVGz@^J)EWZQMWDA7^&5cCXcMAxyI4v%+F`1b1H+WKB>Q z?5L%s)j)k5Ht^Y_f_u=2f7t7PzVzu+@mhS8ax3YJg=BJM%T=E`oO}lbhiUxESBX97 z+CMzfpE(gFCb$?6$R{%tjTg$4GXFYz;&S-lNEPG7y`xVP|8~Pi;V~Hz{dv=W{7L-& z5%^g5&EGc23f-4z->nRK|2p~n#fvwee2FKWQ;(QTu9LO@$1S;MlhG#;Y|`#-El_+t z>z3#|yK93tuP79n+0lXTbLU{-jrKP1AoZ{^dBacMC za|B@QyRba5v}f?J!sEt&?S%h0@ZFUYZ#eQ>B;I|tpHl#YNewiYX?82n4W9Uih)=%- z*zD)D_lfpaB@f4a;pcz&@TbvU=z}Ofka!jr76u6^2<}!;gLViK6BCnwi|6d32kZYf zF6MvZQyG{>*Ss9{_4ONQF8=E&Yw&?E*7pB6mk=iMUHoefYtMmM9Wlw@$e#5l1v_ ze4rkITb?2%sH=41<$ti3|9Gkn|GWl+U$+n!phk96Ct^sqpQk3hyqKKyE$!5st~68q zty_}+gHND4bo9oHQ-vO%Z}@+{bxYbFkB;xN*}qL69+H1u)!==F>^d^IU>x;PVbzk3 zs#(;LSvFWMq+wMysOX=^-Jniit@rlS3x*Fd1*h)*F)qkYAITe_p2RouSQ0pQT1UUu z*Efl*4UO5-I_<_=Pg7w|+Nn#(RWIWjq@N5V2na48{im}`FLw0eXDMk0mQ2}y8*ziH zw;M(K2#~;#zS;xn)zCFV5lZeBVGkI0J?U>Gwyw(SOdqHZK4R=Q($Ie4uXyGE9+med zyTV1@sz^r=V)6n5i+1+LgW z?cY9qNn|fWVE^OO?+|~cd=;#3b8me|T;Tft559qfvQxF~Y`cGMLn4leQ&Y(wVrfhs z6#w&P_j1Bl?pSU0Pu@3nJWpgEQyB+$P2J&g*dOsB6+_?iluT_|BW4EJZA$lHO8XYj zTbS(f$#a*a^gkrV5G~K1+&73IWQzb#b`wMi`7SGFNP;;2>wBHibEG5&T!K(2F5HG) zlLW~$gV3_eF;i1hMaZ*)uou-jjX_!8p+@MaGov9#BOX2kL4VB*yDdfy>G%B|EGH zMl*r)k!wKmvzxc3c8~3@3;)0W;U{RMV2H=o>H%!FXY(FT6z?Z2^jsgOJj-noWO5sK zlVy1jpu{wdqV!w#z~d;9i4jym5c5w1(1jw1QT2mRxa`3(P$!-wVKc9Q8s$%rJ)b05 zOG!#<01*8WU@&iUYPM0$Ilu~TjuX>8dYaY5$`5l~WCTi~4as3T%n;tTi4pP>6*@#m zXQ*Kw!ydV-nxn%8lX^|k4)k$Npog94`{fB7U~C=Gev$y@O!?$g8cVl)4o??OIxcZy z#{vF>e#`dH3G}|4{qIrN@_FYTGuZ*9$09=U_L_$)A`I|R)zsC5g?=RGjPN^#Bv)B`xD>;9l7lsW3#JcEg+WS_LX@GH^!O zg%T1rKui*DmkyvTmw7L1Skt<#F$_evxL)w^Ps-f|3x+Jufck%0uT}^GVtB&$C)H1w zfEA5xiQ`F^ZTZEn*G*sz2s>GQy6y)&PwLaX;}>h)Q2s6Uarty-OH$Pf1Sx z1}Z51bU9t9q;Pp`J}znEy6^};mawphD1=cq7%3gK!U%57^ySQl1pr}`_`KE zpl}3C2mk+MI-A#`Z5H4_;5K4GaUnDsZcMFm!54(Vr61D3Sh@tEZgXYi)PlK+ttE&WDTbjYR%y^m z!P8+0EDxn}r};T0JrvY6b#BBbxLCqnAiM^8R?+L&nVgRk2mxQ=|=M3OR3o|KSs^3fOK-g7zyjl=hf4O0J&5V>gE@aW<;OAd~vR{ znmFX(PJ&-y4j6O@)DQc|El6eqpqhr%B5XaNSSiELXLq2pZ-tv64ipdaqU%Y8)@act z(Ku*1MBduUHP%c+WzuIyZ#SwXS-;B3em_?nDX?d#W;NzVOyM7T7|$c`gBjtr#z&bA z0PVkE9hUv&v(A{PoceHWV1PNAk6VevEmt-UanE`Hc>~bdTU>2iC3nNv*??^s0-cx8 zoapt+4Pb18vtmZ*dQ`_e!HQlI6hzHxa*)O|kjZ#Ax5rS%Q0Y*1%t19sY!aG0@iS>mqpw z9s|n5<3)Ws*KoVa08rtDz!Zl!j=&U!f)^T6Hl6EE3o)r3E)yUsgfhG}vo&HhX60F| zagp$zt^?(<J5)&!-IzPowTez_ z*a?PUy48yp%2gyZ52k3`D~E7PeFC=>04ynZ)1%;iAwS(_ z6-SlcV}^#{CK$r5m(M(lUgp`I1L2Gt5DOC-#-UBg9dKDR1t9c3>kK9RB+w5f_Iv}g zayLWz`t>JAxa;fdqomxl<<%U)7ARDzR`ogp-MJC82+f5{fl%(32HR&fM+FVPkklby zpcM~`L{tkRpf#sia=2bM>)6mgxYQ8kwYs^!Bz15B1&khML=h0tisjq@-m}*hv`K$} zj{}Oy>8h*r1^$GkKpau+>-DFH+sq$qWQcXIgZwlYsMZln^_*kPH}v%rwcJ;FQkXaH zV{GhXz3BKN*4iw0lT?#vqW@=?1f^$icnu)M_z6m=5Fp|{W_##YkfEG*o@zM@R^*+f z$*4Muw7CNo#N+HuZl34_1}tdvn&3JzQ)Wpa>lzTgF!sAb8;gka{=B@r)`FJhLes8? zAo)pbO84Ieq2HZ++CbVU$<~cgb@nl%sFnl${jd46=~in2N!=)= zXrofpBRXoUw3Dnx)!fM;R*<8O8{Zp=z7MO+mq?2bx?bzuZ-(~-VB+-cu&EESHLvbB zIDNaaH9gZj{VzY^GC^DSivvUEezyyVjR!N#iyi>|Q;+AqC4`WP-_=Osci>so9W_&A z&MFO504w9{glRu4d{5`+^vbNB>|vg)?y861PJ*9*eGIM|%L|vQ0VXq}az;-EPhoT! zeu=?@)FUvJvZY5&=tNwU*=sg!$rbx%rZk38+69u+g1SCfv-d3mz}YN9HQR4=!2Lez zm5*%#jN~%Hr6;|LUCcu5Dw30uo(CiZ_^P&v0!vB&h*2vlMei2@0V_6%#0d zxqAAGG+Yy|`_5XqE(@`-wM6s5YMfO2xCXr?6c9Oi8Bj~4I1=L-f+&&meq973dc?$- zXMZ_r|Aa1TK$x!+cmTJr=z5#tu)o(Tu-A~JLsX@Bl`%St$y+;3Q!*7!4e5q+LTL8R z@3G_R#TF56TPuCGzeXjx`~ctzZ~WT&aTHW=8o(vjn*g>U)(V%-U||U&_u>zJ!^IW@ z=MnA@k`Pota$@?V6KPq(ZHel(Otyu2jDdNyMiokM*F3Y)z)H1pU3@R@ji2wfZmT3a zpyL5?KI8AKkH%S>79|k86>O2JN-da!rflAEbJama4G#-P@wsYiFE0$^*hiy!(l!|r zek7&jEn$?6ya*96Ul#}=CL2)^eQRpsLZYIgbtx;3z+sWi)vj9vmUrV-G+q7FU2#oq z2ed}QCS)Cr?M(94{efcIIxJP@ms~9A+5 zuy+>zp0ewRYWngkeD}Zq0`up6`xNZ7Vr}=|kmOTtp}QQxD@4w;Q^|n+E5DTiy#=L~ zch;9C??NOiqQTToY$aup3% z*Fjq?4I+pZcSMJSsD!8W2n*fQPGbWR12+u)@YM4kzUT(A&S=ZyKve$&wg6b8PuN1NZ%cc0K*f%G7t`d?M5XhK1#GJ@BBZ5oBII1zd^@`EM%ua z#6pbh^v*In<7p7|6chavzINrxH)UVB+qWN83k^;qpa)2o9wPjjUUg%`ip-pAJl&NL zM;5ri#?~TCi7Cm#(OnaN@-454=Gt}Yz#@$3$yBmV+Wf20b@iWn@ z4rqv%xgOYQ?*RAu4anXNE7HKee@l`MY33q6%^C!tP}H<>tn*E1JS#$eaR;s~*cw3t ztRjhA6@op4q=vJ*oc9wN#^)04D`3$2?5ewBZZn41Dx(czR>YCpu)3Loz786 zcygp;u%{NtZGUZ_E#N~4u$#3n!DZX*jr!?MQ^iG3%0+wUO2cmsKgID^? z9n2BJSlUVIhAqfRba*XM5Am~s)c+2Um9UB~vq7rh-UC_Bf_a{61NFRM7D%u(Jt=US zb)2E^NWO(+hK3l(;q#rBj7$NuGC80frD{)mRnIG;S3H~6X`=W+9U*yd4{owK;=&51 zZ_Qc6b#M+J1!Q}k2M*eEh(Hbq=co*R56|^4l#BOwwkI4X#z_3U9IXPuz$0b0mVR16 z`v&E*-kH9Ly3BH!RJj7U4XQ-&VAWJKGv-rD!w zG=^2T+AY_KMiEDRQ`{9Z(zUogb8+3OPFf%~nzqr=Pl2EJ4!anWT(%_{M^Dp92unY2 z{TtTx=ht;jnAdGu-GIFsQG)Ag^cMJt(ku*#?~VR)G)JFLLBb1tNbKK0d&*nj>pHw< z>qe&jb-X5wip+X`LOOX(+eZL)qm)@aQVi(0__;P9oRftAd zJ|L~BSH9kR;5Q&JGC`^=vgU^jNk&mwkmfU*Wb_0h;RF&7U$~t8K##-`QHZ8P$O%%y zysF6G<*`<^+Tuc&E=jqp&9On!!_yPRa~l$0yENsrU?9T}4&}HDgATAs!4;UucCJW- z(xb%^3Hh)#_j7l+=b-_Sen68(P6^K#KJaJcmA!^5Zl)cHzH&yU$bHbuGd)c?n*!@y#!8&OyuU|X;MJ(tgQk%`n-zg)O@;K zPI##*_noGrv-V)RlP^4{@xjPMNfXMR|v=f1*NAgG! z_1PEhtAK@Bo&}K*w@EvFo$%y2s%UqJIg#e7Z{S7|ej_Q$%k*Kq=8VYoBIo$!Wn{Q< zx)7Kmwkyx7%ywKRyxenVTQObvO8wUA(;SQ;%)X`h8P~<1-+%}f_gwWvNfhDB!9vpu z(6r0zEi}rg9$XO80&?>M-9S#r;D_g-ZInU!2h0~zMg%)59SJt4l$~b5t zxt*#&o?r_-&IH{{qEK4%7aLnM`U%%QHDY;#MWkeslM6{1D@PLs_6%PwKJZaDuB?G~c z%e3=ijUqH5tV?7-BMCRO2-_^Tl;?Gv>AtetcEQY?$AF}z_rpEO#P{z-)Q4H$_q+iy z$BwyPo?`MHMGzSV_VtbaTEz|`2oO*gUwGw&4U={oK>H;|?rfDpfZFt!Ul^Cjm9{ix z7<50{0yeWO1r{MgUNJ3={R}i=)!$D-2s0oP95c^nv!7r$+If&8_aGlz` zam!ef=Xn?|hkd3L+w%GCms{ihJ=5qj@feY=YW~o|D!hlgKb2ZK#^Dk(m`L?g;kIyes@QYNZdUs60La2!Q4D$`!haep;5G^(A zt(J1KHTobTBx5=-{Dpn%Y`drpv+PEz=w(;Z)JTycYsK4hm4(m!t6V(#q7CaGZgVg- zA02;55kxu1e8pEkQ5fw-_s(s;%hPah^ij6;cj13%y3$mXcL(IIt+0KORS(NEs{AfwRCQ#*VtUCN6EY5sim%tTndug@yT_ zqg;DP@oqtaUW`BP_MOldUB&8@VmGDdvsErJeqACSa-;Wut}+r`qqIHbrsZOv&KlbG zvaP_Nm7}et4DVQIUPBA#(;wwx+b*|NvqYGM9GRqBW_**EvM9DXWn0zf&kjfU)?vC- zF;(4#0)yj~8%Jzi2ak@>37bE@?pv>psK%{i<}jDbZ2!=o>%jVrl4x$+m}ba)ezg+ zgj=bR_|?!oZnYC~YZk9%s2%$(@#ev&Va)M)60WPhLnM1B1pl?v=WifbxF9=JgUGT* zFoEJlG{38%zpf#uflqMFQZwR@95K0!=q(Z1s#44r#Op3qQRWy z6M_0TJZ#$CfW}0XX^I>>DEKZd2&r{i4PVu9(Hhs5nyZ%23X^=1dd-@5aBwVE@YbEv zft*dkJgXe)MROmH%{mlw3y2BV)l#*3*mmC>sAAfZTm?y2!`Sf{HWJJwernYmG3GiZ zi+3U4RBJ~XA5yZPVzZVpq3>Wg(>{02zG}1Tg7i!`E9-^W4`cjFw7~ zb4nh+x3)idj<+~DMMwhuC795`zp=fVXUo>)jYsRolc`o#YMnUl=&D~C?yB+kezt_Q zg_PcBCtDn+{$)>7seQMqVpKN*x6N+qYN=i}8E_}S_tSUIpHmjJ@+J-L-AQbnQ$qwb zRkTwKWv(7gO?4uU!cwB^W;t%#E209AFOQ+yzW7tTHP2zaz^9|6`ttO`rsjpE#m8>L zPW+o&WOv$}FX-l1t9O?_UJ}LN|C$KfbYgg(vz_S&ol34x+x*BeSgdy(s@ncFQcG9v zJxB;5Q_yJci%~&j3Y8{0Ax9Z#KXCr;JJvVQJLVoCDfMM3e;3MpLAaOV72H!!ActHY z-@%L`kSh>U38#F4kMv$er2YAZOGeVtvOFpZD|vmu!M^=-G+Ywll$acQRfCVxT#J3@ zVRt;jCtaCKgVC{d-KWgSQ-Iyn^n8i77XPhRBL$?50X|oZ%4}%v-d@Q+WT#cH6JKv& z{!{PA6w61Fr z8=;rFsy}^MkD%mLSDBN)os-@3(~U)VY>3;0%c@beBYxcAxH1#H6CqP-eR#oxiRo$8 zsYi7wV~g!oD*4La+bS)rtc>}x%e9^8SSO9*K5FnyKTH?qHpvUy4}t+_`-r?MU{mE{Gpb(Mo2!QoF1H z)Jx$-x}Lkz%ayhKkrIq9Zkzw?=53O+`wZ;MgiZ1y zM}2GPK27u7Y+FHR^?eof>c+4#(e=PyaUjwwwq$TZV@H02kD734qJlY+_s~&cx6kiLdg&% zFg}jtldRP_aah}%qvrQ@TA`)iA0X}pG0-gy;8d2=q!^z-nBLsahIIi)nHdNymJ4cX z`?h^>kd80rEoU4x=i#kv`5>dB0^RKj5+=jV#N~1Kw8R*7&AO^<=#eWek#B=M*3{aB zh3YJw=yV?5zx>(SM0|w^gK3#BO4k_fPtR-`8Np4N3Ap_%d{vb07pI*Z)MWU?Ve*_c zHYiXG9hHpI&0THt_;hzPFO{$1U5)%xhftiJzh9jJYpM;&S)o@$+~O-t}jgPR%@6P|g@ zEn?fh25fD{erX}<|VSm`JAP&LeIcwUd5gw1N(Gb^rLA=-5qgH0jwqI_gBJbSe zCWAg#J-6M~0UR;>@{(dzo840v+7Wd^sSD|a)3iSH0?7=>bl`wW8dQSLf8_VP>Dk}C z40ht!s8hj091dIFR#t(JTk{RLcEZSwu3ebF%uv)sx$GPQgo2g2nVc}%pdwG&&>I=3 zWdR=l2H#1FkY^FhuLPWASZqCtAIDh?dt9$!&}c2Fp3$k9(>bU&qB_})jTMYxM6(Og zi>a%muWC{>r>ndSyE&;bC|nZ$_VT-qpF1N1SNu-OzwnT<{qem^Rm}fR+DXn7S0}XU zy`vfuvwf2md?hvNj_sS(iKfz+b9X)~-@v#S8`{Nf)%6*yyJJs`6?biz&7Q&d>_qku z-_>qf?DW6WAH`c!v$Gz*xl#XMNu_YmDdugX@s|ighY1qZ@%hM}qp2Lm?gut8>2*e1 zjFYKq(=K+~a!MW8ud3roH+lLfYA4-GHCJavuJq|@_x_H09kZTr^KLboLntd}ja^;% z>#L6Scjn0jnK`Sg`7ttbp&T{C9G>b7ggh)tf~x6i0b#vrp`3$`B?7t|x!-dPCbZgf z=4C|z&SjzCnv^V%DP9#_o0ETcN$ftQghmr){e8V!6V-8SRKRPyuH&d{LPBj~F04`z z#+=XSrQ@mBDATXx{-D{dJj9~SwIyt)<58Dlz_^((=2^#Mh(xZ5lh0PQTQEIW&Rb?J zbUk{`)I!@v(JS!Yy~BMFhaD(;`S}Y)F8;+dF6RlciM-Wc?kY4w9}eb&o4ZBvE{qg_+PaN1R`^w)fvk)J4TOMk*YSrwyt>GPS6 z`U+loI)jLkaW~fyqKb!Y)ep;xEDxpK7ac31`|UDk+`k=BZ|XRf-X!FiOMSGhC06*f z!z-qmg_5MCBz1!~+vNkBKTe*cp)rhQnyXxAm3*_l*2b zHF2&EQ7AWOwqMI-^&#~RE*!SoWu}8R>INdQ%bcMPML78QQ$IwTZ{_5OnOX7S%BF)> z1lKE8G=hT2*eIjR!liX5SJpWzCQRcbvC+fTEZ-`5cOYmar4}@-^7z~|(2KEXnn=!9 zc4%{xqb(fKbTbj*n89e}Q*>wOXSr65D`RGt`%H~F2Kzkb`fS#ho7@-ITFFluR~_$I zliWaAig^mjrB*+gUlzO55{vOQ=-zM2KEh%|ep% zMtHa7xMQW9W=xBACmVdR)pT0hxCdtqRSx&olswbG>yFkatzw)y zGty^VbVM8N=|o}La~?;W5O&{_Sl(sJdPz{wz|H5FN+GsJWWI8o^%^63>#>5W=Dg|3 z{A(S#`MMt0*DGtwjXi!@cC+E9O17U>wY#9Ra3dS?!K}aa1D)qxyBx;z9}$gJK3ZF= zqwF=fj?S3urY%i1dsmYojCJC#{#t2KRieE)jOT2n$Cjp6VRD*Q9(~YAy`zO@r1C3n zaV>bsYHNLaWW>r!cW0$+rljZA!}__4OC_GJn4%B*zRNY=iq&@}3P=5`@-1D1owa)M zMhvFWB(b9NDEDr3btT`gace#KS24Kpmi4z?u0EC9YsW;gzo6-^&VS6#9eF=fBR0*4 zo<`4BWOtjgDhnlPjOtpgKZ`FB)dPjzm31n7;ouHBm7vQH(Q$pZu|K7N=lNsNlLw=K4&z(0oGP1hpviU}bRZr6TC3SSh6p?b9 zeE-F?E5@st&R1DR)3V0LlYdHJ>NKq*38`bsIX-Ue#eZ)v1u^@z&`F$wjOo5*Prvg)OUngDG0+l{k6MzVLFKQkKB z?-H|!Twf(!H|ZGJdFK#0v!mc(>LTG1KbXCU>Nt9B#Kpj6Y8q0yMjY{4gM(Vwn>khS zi*{XJE+rlrvf+A>4q8$%)xkoNbTKjx=c+1Hc)YWl2ko3Rt8UfgOBJhs$A>PJl0`nM zzhpJ9cbGUAx;hA;H-gygmXeRpb8Pk<9i8Kv)PI0^+?l!j>jn8VQwnNz&dm2$(Es2^{Zq;mF2uFZx+i|Tqj)GpmWd4EQT{_ zF?Pj!Vs^bENw$egRkt8^Ni&P=K}{;}ZC_iP#l`0?{ zv)aNXf%RpBqK8vcuWip?;i+?R2_TtqDAww}y!GkIVEua8&XZ?H7H3#7pRSshwBouI zHm4XSA0GCY*(e?mH?IJG%q&=Zx32nE)yAC@m2@J--c?-Hz0+JHk4^5|JuPxqYgu3K z&-O^CtQRqi5a82|U5cUETA)hb5-=5EGR?J`jv&6teKGC9r6LwRL-&=$6KdZV#l?=B zpex;F7fMQ&1jK&7p_O;AE0XWTwOp-{2;{I$+b8it8!@4ov!ld*ivD$ zDjn^)AM*^@wWTq>sI^EA;m~bC;~dOf316V}@J*|)cR8xh2|4?3n)nvbV4Ka2v@ul{ zQSS`LeXnSWkec`nnm=*Z`Kp0dAEd|S_ z$4j*BI!qPlk?LI=UghaoQ`3i?SY6TOi0)h~ZEb7XC|R@XHGiX1xYW69Ie{jOo{ZBj z3RK|UlnOB*lo9kje(P7a1DFFg}b?8&mL`+;w8*3HE zGd*j}4YW(qMHlca2QO8i2?`6k9?eSmxKs8b`dWqtaXNOuwJJ)!tZh!EckYwf%Ts zW?QZ7FC`Xo(}uEpTg&OSj)$bNafGfyVwH`vcUTfkKd5Dx3^x6CVbw5{VVN-H`P!;_ zNSDOYv_~;3cw442Ht^h2SEoZgdAP~6>9@$; z)Dli+)hp9x<6cwbbWqBHI=EkFr!IKR874+l)t&gvm|+b>K5- z$rSMB+XamAVX@zxL|NthqY+}VH8^#Nvspi~z5QfWSMHL$F`-B%noHAX-Z5R{ws6Q% zp^^9bs`337iskM(d6Ik0xdBR&CpAR2-poxKBw$KydvSr(B5XdlthmQgCFHXjlU0&; zMr=Mktt?DWCwv@Rf?wH6d8{9gjD%Y~H91YoJ(fbN%d1)yFG_gH+I;ZJ1gB$^N{m3N zQ5;$_v)bfL+5A=yjY`hSP>)@|cI_w9MUw+;3AZIWa%)s+`d&K6-N*A;%d9W<=+6qR zYRgZ*fmzS^SdHy<=Is#FE!GIVS434Ed#<%5EU!D>pKy|gK9w#WlV=_;FKJt&o{$n@ zJ^waDwT8Cn>sNu_Kkts#cGZV3aT>-tQXX9$A8M<#tipaPov~ddYI5Ehn#CI2lgwhu zGz(q*!kP10MD3`08~Mhvk=jkW=(ygdG*QvQM2#+D|EQxWhq5LWNbZ^0@tyW|nOhkz zsvVr9m9Ix1C|zF|2zFmYMGdwrDNthaT&q<`G--BnnOED2*r`xuxFl!N?wNH|VW7q# z4c$1N#~GpTR`8EmcJ!Y4Y5(zgsyk_@ohq7dnX0l?__$M%&Kh@ab|}TlkDTLKeMVVE z>7fR3x!2Pi3)-Yfo}IdT*@RuLtYgE7xQgsn2Dh1%ibJ3Omz$*72JQ#HdQ$oiv~6iH zXlA@cKaxF*SxI^8AX*=BG<_p70oVKTb6wnr7=~`6C}*IV9&MM`_`YxvW8(;L@=n`` zd#&`nI8SQNfQo|wBSM}2x23!LHM{!{Z@<=OHOVFZ+Mj#VAduwTQB{ln^ClJ@pHI0m zd^yT2MV55OPY8uqzq8i7I2bh;HNaIe?l^ai!*I>WIJMHV;95Ze+WF?{HI;awNPp#O zE($+17e$d+oa)Te+Lc5KSIQ7&k>UvVELtWL`kQMdf@qhIFCC?f;`BLQEfOC(G(4eM zZ;zF9@W3uSYMZ;1Sbx$*B2YD}cdXF0`H)I^ri(-z&g#fOKj~Cua=E;8Ns0F43V%Y< zg9K^==JlD4?sAnpyXJ)NN+PF!9UaANx;hk-__&=eq#AcHsIgmpQzKgLQy|~&xbC>> zlB$tTTW=~fV(%O`wNTM2nU06$B2OS7&fhD)CMZ0?3rdYrVoye!JR z5p%aiO7?Edopu+A=n)C2lH)GNQqa=&6{+aK;H>x^DU8 zo~f_Fd=%kXZqc@PQFqN~`!Dya_C@ff1gAT?5S`NwT)uyE{#W9I9elg?Y^N=S`5%cc zt%78jn3k1K^Ee+5`F=Bw$^dVdO?l!N=FW2K?)YS^V$8hTQ2i9|=)nT_($Qus752hA zD`(mx*F^{i>WS8?le*eIFSyID?QF!{njej)T*rJl#?pMK%SA^z&~jP09o5O!YCLz_ zjx@PUK(%YEtb#6fQn|oMw|{QZ97iO;dw7wCUuBFQ6N1i@uoQ?(nBa{cZq+hLrfkDF z-V3Z-aeJmimg?;$QeroSmu0xz(BMQls45Xil5gYY9wupK1`m5=hc%?6 zX5eRY(_P9!X|q`FX!qf`3o4CP{KaJ#&vlB#d%1HeXE8wAB99 z5r?ms*+5FF*6v>gS*sRkgN&py7GaDzFTYddx`h7y=Hn-+tU4O)sRCjj_p!?z?ha_1 z@7ONwPSAEQ>vFPQcuL}gEDvnf~(E~FDPXSilxlQ76i%#_d}8C$u=VBoYC zaKt*0@4-+j%{hLFQ)}irZABvT6^|mxxji?wC3>uQau~R`I2G!S@g|Yk)5f|EDEskv zTXS5f3e95%5I#Us&0cAM+#RAfDUMUi1xi>uN*)eDOwt;d^IdE7TMj*QE5kM$ChagT;s z827dHABY1?OYeb?u;44g=_0|zimvvOXR)ZFG>$Q=8Qn|qX_&c7eJ%D+gf-FzT@G0` z$#0i@Rkn(rd`dfCnXOxNREaLKag6G1mse1>8ZRpq_oMhG)4^WzEgPZ7A|)epM^O^J z?m0FUxPj@%MH!^VVqIk;yr~=N-OeSLWKmBSw-rlY*Dc`@f(5xvv3cUtnQtoCxXQ3a zU3U#@PCp!c&+e$_By(x8jn?8jjfICI>3F&WsXO{+iH<1 z<7d~c7(2xg!htoW$VpUw>x`|3DL&n>tcl#g)HyjHTD1}3rXw2iT!Vb)^c{0THmWsc zFDX~B<A)bj;#>{kytAhh8!Xbm+^tiY7t`&XGBsb#73TS!_*8Ov09yH$d7v8BI zHH#y{jC_W}`Ih}+ zyGQx++S$UY!Y4BySgLJ|rkRzrJ=YjiYM9)GDrB;GK0dBGr)Z(a-(lO|c4v0Ask+Sy zZR<{LFt|)fRQ&E+OgZB`-WDe z<{ypDEuUYgkJJ6>iuc;}K2EsDz$YH zoF5?x)`--Cj-%&LI&!?Bxds)fj2v7Phr|4F4kUQ5uasx_oo7w1c}RP5;hT+5devOt1)T$5IrP4hE($w3t<(l-JLcR` z(Ma1&>d+Msds=}$SIEXBt3FHc(*c(_cp|4&=Wt?=A=Z~b;vkWrM}?b59A}Pm?p9_A zj_3zHrkW-W{XRx+_ISPHV_aRn>!7)ASG|R0l+qUKOy$6eVjR;^6EO>Ry#-vQ#sw$M zhh~H4>~+a@4bQ+PO4n~;W_GcjuwtkV)w5T)3;T$D`3zH$1}Cs{PbfFyM5R9k)4M{ucG+T zX%p_rN2F1$9<2s_2P;VI=!i@lHk3TqLeuoMN2y(%hY3Btq_ZV@H>mDt}><2Wb%dJ;IlN3)3fDS52lSpR!lu;^^w8^Wy|&ib#@Q8 z+=}`(bSX`xs08J&yOo}WIY;Z^;=Q>w9D2ny)vhYH-t-$m;RSq9lBbW%Q0~*I3WR*olpMKb0;n&|9JJ@X?uiZ8k3{>ct zXmZK@&0nUGhJIG}zU~tBf>a=AQXgN9xi5&1l6NoF(ZN}~zxKMm)$9@*RRn?D6ZYHU zt}V}w3fTQ%Hg3K(uW|muS_bVg*{cInO%lu|foF%cS2FVA3Bq?SK@ltOSCT-H73>zAfr_s-5+ZqJI;oP?Njm0HD3;s9a%!OE={;_*tMT$7 zQJXr2fp=IV#*)!u$72D;o zo_a8#xF%!l5&p2`B)o{C|#V;0ot7@k6R=^vIcqSizlsG zVuXbIJ07yc$6y?K*>gl^q!eBHd>t5t6WSbxyAQl^T#KwAvd5k}5`%J3#8q&}bkq#T zSk*abZr55KOvE#(!2Tch-a0JmZTlaWQV;Fy9wLZn;i z?x90eVqoZ+A(XBeq+^KR9`xP==iYNZ-}CqHK97%&N7`$m0JG)N#3}_9ho;|}o9d9VPM8={SIb+q9y8K1< zH0?Ufo?A!Qp2SJBe8HNcM`_h)S5Yd6^o9eIJQ&pl^uq|*8mXW`a7J}~A4}c9gihM^ zrPwq!i$%BIlO;>lwTWx9s+8ZM69tMU(%fm@yG~J?Bf|U3wcDc`yI4E5&E z9pG2sRV9k8$34sXCfv_};jyBmwjuTk>+OhG+Viep5BEzN}}_f`^F8IDt=6r z!f$u%JCgHg%Zxv>b?YHJ-x)-5YUma6RfW4uVR#(s-ZIT58%`k%zHrXs>`ZA7OPoG# z^YlJK%%(7W*Z6!VX(hA0#Fpm%-jM2y(vTBuQGpjDB4rx&C8)6$O{zaMuxMjZTLdK+ z=-=lW<`7+rC@*}8qlW6J^QY~A}!Kn`DxNE}*UASu% z4D_D+)_e$m8FufS7!I|-muxz zX(T|u87rw2kz{-E8o`fy((~?;4KJQy)d;iSw9Sixd9HT28F;$v*I}@e> zBojahprBF)*718=?k1Ct#rdkc6VtQ%H~M?P8}_n+uK6TH6_NM5%CyF+zN+t9k7uyP zJHB$K-xZj#yD}|6TJYmy4M+9pb%AgeMKWqA$=;Ul*Tn_2Oh_&3ET>?oPN(avb7GDa z%O$ny-W*~`rM_ffoGaAN2vL@o!=BKN63W5`Ajo=)YTNzy3kJ=*1hF>(7=u=`)OL*k zvBkbg1>eT-^#G{31(&}q!@GUCwJmfPgb7cYlbfQdZgc0%E$6oe1LT{Zl=uZ<3a!KC zMzMUamgw#nJ(n&Sqok0g$o;roUSa*r)!HCgw@N_}I0{VBu4$voPnTRiWO|f2JI`&j z^b0ij<=Ufrp09c3>sAU53#ipbmud!WRS?-G%2CcsUFa-pYMqHgJSG)v#yIyK)T*0g zH8?vPm|z`*Wn9Egbd~F_dNJ#BhJadzG~O}9NxRsHB}^1ulZWQQi%wS;$y(M_%$9&W z#=XYSd1IKwYA>~>ZRA9jX7fQ!1q_io&0<20eRXJH(s#5)V;$O&>Z#p%vLGIi1IVMhQ#)l55tpoq@_FsugysD2?pe^h#-4 z=ia^<{E`J@Sn=?&>kwE-!3uMnw8NP`GB?00j&X5hY|pvQguMx+iWOfDI3M+9@p&G{ zr7z*R-uNYn7~PucwXvtEXrz?kHCF@$fn9;1!;%goK@ephKiXl}t-8RXXu|4LiQxT) zbO0ygyqGLLd z?fH8n6SjixZR$QN({)Nw#7w-+%L08oD7S~KQe9>rP{ul7Bs$t|d+`&AjiKIm&%M}I zX*;8Ng(`DXbY5phN@rny#?QPYjTbB79a5LCj`$C~LWt(RPEYiP>~|_V*;-7ll_B>X zpypbI#({CpLj&+aSPzH_voB&?;i$@apa4+3^@|1;mDejmlHo7TlDQ_5?3FjNA;#>0 z-*)?{7I9@eG|278XcCSYq>k!+cZY{&CujR`pD^ogcVMA;bx!c?{Sdpk=d|)eq_gZ{ zBk3tfNHof_)58vA9WoPhLkr2LqrYpAlht_a|O4#y8M?_eydO9)$j3b{3Au0Vc zz4DvvI{0OHNFnbY1qa9K9B{Q29z34L4cKe9p~&VDN@Kb|aK)H!*4 zwx_Z+8KbQEI`(#w*+5gHWC7-?asiV6T}yr}rjH|&-_eoyIQZSze%1Jxw}+FF=@x+9FP1{{ zG}r*RfG_C+C32imGKMn|zE)$I0n$aMhzzxUt{JP8IK{HFd45b6Rop+jSn-0$2|-)^ z;9_S#^6J7}*>%o*vQYuLhT)r=D|^%atM=_=vonbmVY@DgN-Z@;O)?xrhNm-XEmhXsjeugCM~S6;Z-Z_P+(e9NRpa-&(x{{1I13j?f})BTu9 zD_Y++xJi38lkNS@gDCUQQqW;8WloE{dl!4EV478ry?W*n{N>1>4tTsBjd4ha(|>T& z>639S`^fZPZ-ffYz0_Z*tG)ER~uqY*O~T+~r+BkrH4?viJ7-_Z*hGfX}jvTj?gqj9gZw z-TeAM7;0b_m&x}H!;Dy$Yl=jBlgc~NIc*xJ*Wyz~VS#%~PkYBy~vpjF+fpu3W?NYo6+C{e1D|>8a*t~JL3CFG~ zPk2>qlgz3^b$CXY&&G#yEzH<~WtMZyt*obpZ2far>%2Wbdq+j*e6t9mS%pEAaWc)> zRicFYXAD=J>l-sNdqVLs+FoRybaX~i{JcSfW_@S1N+_RO@aBlPz6(?{uhzEA`lXL1 z-AhPSP2k9wv#Z}4Kj#bQf%U!jl^(rPqO@j;5>*F|^;gGsVOPh#RGnzwbHnf*3h*Ax zMcUze3&DAd#O2us#PK>)3fZpoh~RCru^f@IARYD`hn=rIDW8Y84BBSVMIGoqR&>c~ zO7O-*l97Hvea24rW z+y!VCSGj^?Z;bFpHs{tYkwbZ1LbjF2sw9ag1n8T~#@xQik2E1WWJ8w3?P_cU`zNt3 z{OzuN!7v=N%_0o-75qKYMH(o^kxysSa>KEDy~Qm^JD9|{XZy^R&e1-XraC9lEd)!f zYaF{?Vf7AFk8L*+^*GqIG`pqHb8Nq9VUTXtpaYIsaM#j@^D{?0keX)}Y1bHabME6R z(vRmc&%9LP+qNJUq3+?Bhw^|3Lwb${=A_{Q#;bodan z&e&~R&014K`Jrs(-5-Kc6)I>~Cbr!l-c+qTf)?Xk^C>$>+WGOl%NC-On-jjSBSA1~ z+};7HD#Mr$5$5D|9^RwR+_tl<<~qwfJH=jcgZg|mJEne2&(Rk%Lxqt>* zp|`7*w=jNyOcednlt7UrMC!icAiGUE)Y+n|dXPU#zHdicKDyd$VaEz&a^qT)6;IxC zZ;PoK9nP!yOjON&A9g-pt;R0U&>=IEh})hGdM*g{jh|O*G_g|k$<+bbAb!RoR97oP zcv?7H#ptYRc7D@-L8;A<{%Yd@l%6^1;#q(0@Taz}Od55Hh}giB+SE1z9kpvFDy2?= z!%nueb0&-hCNncR$+^J?RcWncKJY7cyPu%TwJ?Q{fuCPpxt6ZF-suX431_=&+Vx08 zLo7aJ!Uy{ljB={%B04ri7wZ?(H;1Uasi% zpZ8Zq^ohwkyWuCPMxbYcv||}MYN{V;?!bb_FLp|;QCbHxY*dh3t-u2nlD)y@Z~N5w z8n%OoA~UJ=;*8bW7JL=asKCo5v6c&PsVhA0i(3p`J4XKN#(@&%&fbdyUZ&1A+viK` zI9|J|m+OWR(REnj>TE`#oEA6C11oM%FX?)h|VRuJ(LK#d$-Fac^Ag|o6RIv!1et0_=@^tp=Q>veRmisu)r5}=Lc*hPf zR`J8eEY;n{9>GyMZwKM57cSVuT2S`@nyE4L1OiijPtacaVYU5s_Pkw4@8;G9p8JuvTP9!uKOV|A+0J)hG) z!svzpns9ny%PhUAkm~%E!McDrH*EtXWGADkM7-_Q?3b#Oyw{ld;ZEQCak{d$x^P?* z@DEcGJgZ#IQ(SN`ABi{~f+~5totM;|RZYdR@hhnH@ARo8U|!kHmC^T1R{ZAm+cBF`}NlzqCHRp!w2>`D_2 z1fQR?d2P8ATOxGbNbO0L4*muwaIf5Jd*X?|$>%f0gM%t4xd}T4xwB0lvf;4-&>`D% zMQ%X3I=IeEQ(&)n($(R=dGiL`;&^)Ep0c%+5afDdp2tS@6umBHm&zceMX4)cC6NRk zyx!=pRC8Kq(dlKjfyqIYl<~C@q>|G78*0wzIeX1?g~K4~PSvP;++ewh9&9#fWXca?+0 z@RZ7>8nneC-WaS-P>o4-dtnFW6iC8t@t{GwMsZ6}GAi35|4G`)bG=l-_?dxrR97PV zwX6twZo30o`yizkWv~f~wxWDw!B@>Hj>rR-LM6ANKzoks@uD^BJCRzEywG=b^Ii#x zpW#x2rro&dAJ-b~&%9QnmQ2s}6eN+jL_yI^n?HY}rcyBvX(EBqa4R;dQ&fw)=Ky87 z1z$WFe~JWpu(?{AaPh#@xuS8`{eBvi)2yM_L?xVqG4o8UJH)w0T_>y0h@iR&J$j4k z?1pteF^+k)bC4+q1%bMoCRx|qp!ulRJ9s&JuN&H;viapHB_$sz`|>ua)iTUX45Rfz z+;(}d!oKyXxINrU0bYEE8c1&79h1c1<3>SI+EFDb4k%|CEU6)B0lg*F%fU(bX$i9W zKA+l8P`w+LGb4F7z`D>+=~Lf}*I>|0mjN^H^njMF?PWCoFL`^^XE=3P-Ak4%W?S#wtD_sH*V^m)R z=2s576iRnpR5Rt@ZN~&Ui;2irs6c8$=68UyV3G*ct)=GW8&ZDe0!#=*#(igR+oo3QrW(M!3z<0r!UI~&zNp* z_-E^WCJ(j6q%k=u^X!+P!c7UxHVt?-^7zq~Xxg?i#YRlwNVdh@FtIQSi2bXs&e3I2 z`w;Sje38W$uMS98qR${Scj6~23&&cZ#r@*$@(o&%F!Y19%f^d%t8M$b@ek_I^_If~ zgUi~ri{v(T1L5YjUOlOL$T(YZ)|35#X2bDiGpK2dKbpw~!vk0MF=C}EX}opXaKX}g z+AKtHct76yZPr+DpW;$Z(pb~l_|y%zQKeCK$!QDl^Rt$!>crF&68Zp;S3y zD>MEPPk34_e$h@Qab`l`$qWRPXKM$tiHm~Cc3kg}H*H2E4$>baQBMMo$^N^-JMSE6 zx2BV&b1r@WA(wY-1PsV(upN~^PV6^L!$c2MCN8jdRt=VSOkfq)x8+jI0~c6%1^j+0 z4b#F1rw!%$LssBb``4^}3!Wa2?`K=2FdJcAcJT*S*OmS>+?Na2h|JJpw0cOP{tPow>)Yk;~+_f-_^3`OU)ITxwK?C&g4yG8wsg3ozqoe=XM*3A8X0sxssC5 zB8(bN4=1s`D2uX&fG)=FpZ@9*~y!5?2yHM2@GlCG&)l^}QORf8{SyVdu0 z$`q>5j*N&*<9fMQL%Z=SzwR~<^=3|Hg)A2RdBrVk3b*FmaS^CdgEs*+#a)X^HZga8A?+9S&4VmF7W&?t#S6M z0;dh>;v0yt?N_qw)f=#t76}k<+ebqtN|!oRTa~Bt$elz9@;%DT6NB#er6*!m&(B=X z!f|ac8(S>4)%rNXN@_~25gbo5O~Pg25Y?nBnNo{4G! zeySEvXXqQW=-xx&ol!cZ%R*G%X#_7V=c2+3b(=As`l|-vu~RV{X3@;|?H|q=Bj%ov zf9!J2u7Z8Dqw8~hR#_7^M0yGs;%(-PI?Wd=oA%1QlF4ICYY)RL^uu}jUaxawvc?q2 z-ll;r$581#(|5y0XrH2ytNsfFJa}!K+O^xHMfJP+@k)txKNrp6tAp-qUftGh8Y*j- zH6i&`j~;0*A8<7r6w#wnkx4L%ggN!w>6o|i?JJjJT30Gvv$WKugB~=Mgrza(UAnxX z<<-ozT_jxqOUAURwLcD49Z`iERW9|q`p`JCuwe-K%X%mFFSQ58EnU{6xXeJ_**|Bb zs8a*$vWHW9UbpT{vn`A>stq)}GW*yM0J8m3cnNN=3aeKJ^x$8gI1Qr)G%Tm3y3Xo> zJkqk?OIq@^%bgvHnDolvfld7F+7AH}&he2Fiw8ZFV0O$IE7P-+5KC-9DBS_5yeX{8 zJDAU~TiIvG)?2T<+dUR1%6NaqZmlXXVW}&y(wxhlYj(JB-uD4Q6I&m8<&wLq52?Y# zDBT^9g07Q|)QXo3`tTJ?F(V(J*(CN&B+q3n5=+EzADv-+`!%I?!z6=CMRo5lMtp7;Lk5GT`b=Nxn__wcJw__%7}znu!OPJYBErL95rVAZkXPX z@}rSAicWzT5|ct}%jfQF;42X;JFlSA&t+WjoJob|07fbma@|gM4xmbCTq21U*#4}& zJzJL@-x|YfLG^RqfYBh)`q=O@aY&>;7e%k}_&|n>*f_B&kcBDHR5NpCo)>HcCuw zGm90Gk=z%DP*(i52XyJ$Ra*7eWkVPYh16yko~q4b*e|b6BbnOB3RB^gI(XLJ5+@#I zPgiB@&HY5o?Qkv+`L492n|!<`nrrM(MAWoEfU8>C0dUQi-hpJ+z#ea%jAf_om<8`L zLUBw!wyYhraoFycz8Td?Gya*bm1mvx)NTRMS&>^>8)3ND`?6%!gxK{iIZ~6_BE(fV z3rQ0%^>Jh1<+v?Xc~6#AWqzCm3r!cw2~)P-K5{;$wNnJClzk>^BI}nDOS9dmkyheC zN>(LyyEd@C3mlCX!8;FAj=-EON#sN-lh8=HnPtk`Dxz#K?ira5_6VZ*_!plxisPM; z`N^e%HI)kN1^U4O?2DTw@_L&;y%|~07A>tm2!y(Kn}x!WT4O3Ksj1-@UXm+`PU;Ml zd`V6jppFG`car@8W(?_OTto!3`57ei4mt8@-hO)Oscr0%U3IrQ_a)>UHN}&C^B8h- zmmfc_6|!RX_r9*lIU2WKXJAjGz&A>_zt^Rc7dkzda zL=$63A0+lX3cqW?X;0Kme19i;LN<4UIz@c_flALtOr7N?Yra$p>p>}2%`ReI8|Ms) zGha^np)B2kw@ZMQN}`CX-il0JN!X@IOBS+Ew+9$_OA*siCEnJ;Nf-{y@X19qw$y!( z;@r*oHH>#2tUdM;1fxe{aL{p;V#H}oJ^f*oW*o?-m1=Iex|a{A$L%!q_Muf)T=u`z z;AN{1zMpqNhGNy!;F!gCU_;4T5K4mL)`!`_ zB+j^w0vuG2^rGp;M0;FSt4o%>`Mrf)J160O%IQHl*6HAL$0h(NW8Ja^FVn$-hPdy+_+nP2 zFC>12m&3SUzka0`igFpeFHePEa-(SOjN!uNI?a;Dd9HWl&M6$^iQO`@pE9K$c-O=c zsliLJ&{Mt0E|e`ORBF;wpSc(tiDoWniNoJGJtx>R!+(flmeN%Ff(%0Ze%hJ~2qocIRXv3go?ekTvZ zom)OUy6C*i;1meh?J)|uQPdVx!u?GOP`tU(^vPC8d?G=O{O30y zs+}mOTTrj&w5>}^Br;>I8DtvL$wo>yX}DfB!(= zx#o4W%XdLKdC^=+*`els z{fc*hA>J(yZcq-&GrNz~(p78{lNZ#jtxttrY7aZufB#O$n=X-`A1!FzW;64-1#?hd zY;Ause_gr`y5pMold3jv{YH|;fNI>-ADEmVOh8-@3H7k^tvICzFiXr-o=oE%=0JRK zC1W``uDzY~eiMBiOt=b_v&BDZerE_}|xVJwM=A<04vu>X|;oEILz?dfp@I_3ii^ zw|!;uO{@XWwF7^1+V3i!{1RrZMJe=2$&J=54-^#!EW!febM%;{p`uno_Ij686?gW_ zZjE|1dN16U-V`d1e!(JN3egZd5R|Msyy7$1TX$!UWN4>0aN7vex0+gVav~M!_yX!p zw859vx-y?QmLzOcTMgXV2P#OG5N2yf25zgy*taw$uk@2b&&jO!>Chfl}53X z)jn&?wC&U)?|z}d@^2kM*MXgv;fTkEDSb%ShJ%`W(5efPAS+ONrRMYU)b5k{kd`ig zX!b>P+auKZs9l7dZAMED>JRRzPp?Dy%M>;#vPsbB_`5p z_ZW^=>t&$$Y?nHfzJVFNFfcuRKH|3cVRKH1tS3OHe&&6$MNtMm`*!g%$f^-ON&{oD zHr}a~!Fp)(BB5ynkTh-=84(`ax^HsYZq=!OKn^v(12a{J%OCVv68Z2X@vnFp$?0cZ zH?jZHU^e+Sj92_6e{G|$35nEL_wK}A_)0HvU|fBIbI#+(1Z-=aWmfY)rKAjzdsH2O zgr4_KgT3*)|9Da{Ss5)AHdp4_+nl$u>Z=*;#-yON$P(X+q~uVtRW7 zdC8GfMEVbAUL-O_mT64G$8N8;wM#qMO6RU<7!4_@ROYBtaj|@mLYZ`YjT!3Ec}DmM z|MRYj!_0)DTwQs>VsAyV4XQVUUX(7metPA!N{MbUvwD%34Q-E3`gwzqJIpr+6VC?Y zfK((qE==hI3}LI5YPO(l)K$&R4l8wQ{WMPN6kWhw{>xh0L`H^%tr_b3wvI;bm^I_Z0Ks8Kz=T`Lh}@+ z3rW&Y8#pz61V;By1Nb}<0E4uOv-ITZu|b5kVszP{PaPjtbV!U|63}fDYDb@>!PRdc zaU9s`$XG*=^#v4EcD@fiDhg+5z?Xj*iAUfcYDMg5z8kY()@Z@XeX)P@!Jn3egMS`i zhDn|H0z3L74)T}r7!;L zABO9QmcTBv`G)6?FG2UmWHF(@&{+8&&dEr7)K;T7Ht@k2OMYVANVY%Nd zg5W=N#qR~v)e%q)u!em53TA&+U5s`0c6G~DdEMduH@Lf0lnsW~e()!1QT%mZ-tgkT>6Gw1(b^a+9P4QW~Z7dX)maEW} zci{)+(K|jzzj*?;;+)}g1-f=B8GZ=Yj>N@dTRM9!sa^Hg?+B5A{VR{lKCbHaGC20* ze=Gz1Yf{c*eyF0?;8)`2-=D)V>;L^=W2}~E9D5=!T-B@4o%WaK0^EXOLUxYuVsQxq zGu~r_0PhgV2t({QBo48N>F|Lb&*mE6xr@|u<++BMXIuLl0K;P3cMB9xC$v8gMJwtr z{(FIkjmg^JWCGq@{td{c1zwG^D|BzzCA0oD`J&G!S=puOQXcU`3+Xz3UWC2R0b9N!qQp5| zvj+A;M)^8NMvW2DZm397*W|0+{e!MQvGUPJ2nk{3=<#&o_`^^?UxJ7CAapk^j-LbD zZP41~UH+B|duVjKfWD1m-@VpENaG!4X&>26%x5qYp zbdBJR-dEr|wk`xOetFr(^nh>l-Ku}%Ss!PJV@&&pfD^`oMHH0YhIwOu==W_EeeM5P z>|d`)C>J2NYAnRQraV+k8SQ`+Ce{o0enETxzdcB31KaOD7I){+f$_nP#(zx}_V}-P z^j}kI|Ih{9Se$v1*KZFwGYO6L%&N>f-XHbM{*IJb%3|l`)hNvVZrXVdUWNH+-}`?e z<1d0H1pz-O?*>V`_TfHspMZVnt5Y)l6Q;-qKf78w6=i|_T~F0(;7FC&@g5v22QJQuq>JUWS(*-*fJUI6o-#?*6H1=u}kJ`6GoLiYwK(P&YKG8pSG~@H1XYj{q zVAp;Dd@0@IYtpaPegP*Ebn(aGw*G<_|KQ5smv|Xzx9?(7#`eCxQhWK^gSy>LFjqWCKnen4f+*{ZF2e12zKZ zlz7<93sD1&rs01j@$pgUpugV-4n7|^59g%L zU*UzPF4zYH(^t#?<9Cm09H9|lh&8wn(W!^~Xbu7UIMcwU`VS<8P8ypAFlxMyJpA2K z5wI(i;i>840H1$mgyWo+aTlDTiMaSZYz_p#oML-yS!3TtAKLZ5|LVWrWdo`bqEqtr zGL~pbELgE6&TV5m6x*X){u`Ci0?t&bJ1Zwg0y|1=YHF%GN9BRhXm!Pfix+Qgo1Z*1 z7lZ(J231hT4D33#Dkf!-0uKfJ@Z2(~UKHd%?23mM# z@KZmrq8(Q9-S@<6cjmJPN8w`ts`LXuvv>+MA4!o;6i8?sOh7^{BC%kI`E3lP=MH~rV2GTb5?eY;yN)-ErJ%B_a24?C%!W${e z&d9JFwK(XvT)*ajRr?@krCbko2>^vEKN9Iea2WSKWp^1!62=1T0iA zx83iCT8uF+4G7lm@0d6OxWV{+URJmGlO?RRTjR4ZyZue1g&@ytlK00w)K;Y(it&bM z(Ay2^wJ$;WNl8L$?sZa3-iZLW*NwG@7Rx#HfPc$Qov!&Ox`3BiW&sa@#iga;cX|~2 z)Vl}342A&|ZY(~}0)D!*;GRua>tI>2=j5PAajmA3(lmbh`W|2~t9qPM+y}@_MAIGl zH0~d!BuccezMNyzZ4P04xdc!GTfnI9YpXLI_76L#qWW8h(Rpc}^Ml*cn_I)Ht=8CM z@q7V9$Gc*g)EQEnTZ=9$ud#A_7OQ+MA*27qH}jFD%f~}tr=m;5u(yETjb?-$xaQ0e41yY)+2YkA-7#-@rU)hM72P zDVqYDQ&~OywX<(mekF|xfX=J8sXq6A8KfhJN|-97d8(w;sZ6O00Ni@(0RYhePMMD$ z8vqYW4>9{?@GUdX@JEM{e&{aYoU6A2B%w6 zS8ESC#HH@3i6G)3_7OV4{7Nxg7Btk;0Q%DE8y4Y==Z6pZ$Gr*uF3VByfAb0>SQY=t z8zE#{;@=S_FU9j1VENLx_Q4MT${)iiY8#o7I%+L&oyX>pfHW!pn#>RYqju3uJ&d0{ zB0&=sYk1aPD-4zj%oV5UAl;4&pr7KY@2r2L2%f4YWn?tpIgv*2C5GKdF7@*B?i(+K zj(@@P?djefk1`fltc@a!uDQN4m!8ehj zqT6I&nf`2Nj~IFxa!-IpCI-;S2#p8uL;r;5YILa?fSbK~^~$D@STd0Qtpc$v(!;Lv&A=R~VN+0ty{E$=|Irx%pLJ9LU`Aau`6M#i@-lb43pBQM zwbI!9%?{2=2rVgO`nIoaTGV)#ph^m&G3c%`!QelAWr!kU9S3#p#*?SPH2iY!3jrjv z&L4`9Zw>FXqGGDxS(W>=M`cr_1lU-W>C4gLSt~<2| zC{Nfq(W|m3Tl-*uhaE^-2cXU<1zgJ4mc|5+trGZoh!S+`5P-rByL4Aof!d?)h!*;@ zxuHYhs=fwr$9iyw%#?UL%_oP};NSa5VV0S}MKJ0znVQ%x0z`KC)2B~o)w}L*&#ZjA zV!^!^B(P&h$>(4hK7gVH=6eMI?(u5baCmSU_hv9&d`M)db_ZJ!@cfAlR!!ALSmCi; z9dp9mRo%XSlRnZFsi*Glf2aqL+B&}JMxQ)RSr31q_%nu);o&V<5O|98i&R z>gwuW4FQTMo8yYEO1WinPaTjKslgm!?~_G#DAn|bv%pNI78J+?@y_4w2(iZ&-rC>4 zf6utOurHzo0YK!RYD~Xc);#1LRqQrSzW8e#DvQxYg|2?O4bM|Fw*i=eJBQfb3a{jF@4-BtD$LjW;71-Q$K;1-20W0G0Z(q;w@>b}mmM_Oe#C_}PD2G!*? zFJhLTj^U$+tHNd-ZZHDP^Bw>t$nYagZY9$mKhvXfqjI4@v80qx1$@4UTaW%vVZ{pq zV>2Nn{DqlAPDVz^6f6=FUd%C=D?AMdDIP{IY23JYpX~5gc|cNtx?un!HTzf^gcaHc zQH|@NVt<_>kWo^i52Rp?c=C=)ERsdz#Gg_#&7Qz!UQK#%SR?ZM3F4`slGITa*(JWN zVgu!H=tI;_q1Pac6{WK7&ryMg z0el(13|o~8$Boiao?MalSl!qjGH>HJN>d+E@I(j1`&)2x*=d*i%M9aW`iU9TYVk;v$3Ab1HyOCMrv*P#gxwbzb4%lq2=i4DZgLL^skQzMF1)p5XH0{YF!_Bu-z05o~|qK z_1M&-;BZGtb+%a=2acREsJcJ!ug4rZzyGZw7&qJA(AsqKuYJ#-=e}3hke#VH_6bjB z>{Rme>|uvwC&Z@UpH^9YXWGk7$N604Jjiw3GNeCDfu5BDWDm8QdSt;pU=eZp z7=e!12RcClZi~c3)Hn5`&k}L~>+ny%t8yNDuAW!1a*$;Gk?Rx_?cbDb>O}#M3fx;e zp1>#qRRD;1r^HF@66oTvS_0J?Flw1M#(eQ8FCVq5LT;xmM+F3t?<$Ty>rfs^rPYdl z2_O%)oFY8)$bwW!fc~#T8joPWqpmMz-yKyygt}sYl_HX&&m5AS8)S1t5#i)DKh*0~ z7?1Mu5mKG-+`aI<+SRS>iuJK){QwgrsT0a{#SSIM3Y)+6f(MLV&2f?V%cAuO99qDm znEKA+Iqv57fR&hqA5b2W-4dH>EMa1BYOHW8RyfMbe{dD}*Y=%yN6fA%*Ysfu|6e}+ zXDrqqpIOWML%L21f$ieQlh^P(-;TQZS7bkdD*$+O(=++d-~KnfLT&+8Qt{GfJ6ysK ztj0A`mRj?(-qX)K-1C3?>wgLh(C>c=>o?c_PhkN;{hz}6rFj0Quz-^OpNI9^%>Mt@ z!+J>3Ia;I_=mOIBY&zf0r~tg-9yx44zrTlpgd%We8?z_F>@6e8}f*j2?) z%A;P%anFv95jX?Ck{N%z;TcEh!b0K0UB-WSuCo?ZhMWYkb>u>RohGl{;$;g*y_Wa4tVV1H#5xlAr&^iv-$IyKe|h&I z*dBpLugPly`Y&kybrqD(85=w#aL6AIdaChP1VA_KzDotDdrf`!CW{D@;%zaZ%wBf} z*_$a8bS%Ooui{Ci?Sc}@*6G(;LvnzR`T7EbQ<#R%tuw;0kwg3EfKk;7CpLM)FBhK!t|>7cVng5C-X900#8i-PfiGLtvJ$TzPAfa+ zBm@2tVgxjlejNDnX#91;bB%b?RS2^_pcOfw=`3kp{^R6aZ>GH5Lu{5{A+Jj6F#E-6 z`dn^FY*WahdfBgfrIiV8h{gJb4qFAb7*pKjkH(h05*()~4ID@e1wrCptd5HuuQD>- z6|*6wxGEvx|LO_8+ZGrm$ZMOm>Yvv{a)r|e1VmQY*a){HK=a_Dwm@c~T_cwR(`?zC$#pS&TKG%Tmo| z+R8>XS=o8-6ZoB{ts)-so8{IEyc&OGK#478-Bm3iTwf`&B<$74 zsY3Mx%FkOVQ%J3u50}e638uLVYJe0ZcY|pKHT_7bV+w}W;pdm?4r(97X+Dowq!v6M z#4V2J0vO$Dv9O6(9x@ps@)48BESb=vEA-vM9TQv3f|OmLHUjLge{iOK0;E>2JuraV zM9e7H?Sv1zZjL0Ya9%pB_57Q^e`^uXN4T~>s$H++{YfUR?qJz}t|uK<{%S(EoJfr} zL3eQHF8RD$mrtcU$>a3mWNkbIw$!!SAt;zBHt117%{>67nF;#(`WAssYJ)OTzMn!o zQy=6PnOCCpfr>Lasb@pjdl;YPv&7BzLA2CemcMqD>J4bvhev8U-PwVTk>euV*uwX; z+_v?)=*sPysO{rsU!BvK#*etGMh~*a`KBY4ia^!ergi!0Ir~aoz?P~^6O@b}z;wR7 z4V`X}RgQJ7(Sd`iVcb4Y$=TSVVxM2KsJ5qW4tcQewPTY1+in!ym7xGS4*6m3xEjnP z1oEOrq0}e`vYfVA&lrk-I%ThRcgq3hbbe3Cccbyk$r9qzr{l6lb5%>9ao04_x~mIp zPlnA}R*)JBuC_f`8FgN2NfP$f1zZ~;O5^y5ip!iCBvR8s$HC*7Forp7&yIljHylTY(ae*^yiX`5~r8<>urn# zXR=k>{iZMRsYOL>U1!6T_?d95h~28QNl6_`Rawh$g|!|i zNp&OI?4jt9RMB7>Y^D7RiDN!E2llI6W(anb3aeCh(?J;^67(bOn9U&rT80qvc$v1a zH*ZdFj|Z|&g6hPFuYnXWP!+|R%kE^6Q%y=UBiS*Nz?`u-J^W-KbiB42nrg3XLDv1_YVtxs&?+Fk{dBT?x|CI~tSArcoa-k?ZKNG27Qz82Mve1k z5EW2>5<45H1vg@FErhNStJ~{e3U*bwY+KD-zv-M#Sf#3A)Ablm&9gYB8I0{`%h~|9 zp!&S)&J&-dk}~~}cdbAw^5(>!^0!#=En+&mvAQwTr)zv%ug&8o6B;gPBeS|y8@9_Q zg0k&mtx3j=Z!0lLFWfVTd-Y^q)yTyklH}Ta&A&NJT3`;}dZ~PZv_qyKeht_$`)D@3 zHzg(ma3X7ydS1>$cghhco;Y9yV0XLA%+xR&VCbHN+k9qv+}t~ANPp%-O+AmB`&%Hj zK9%fGV>K;|*FpjiC(?3P@98$5#d;(YL64b)7pjeuhO&D?HXLW-XHKFUwin2YmHj5MYB;W!V)2{hxv{a;Wq#Bc-mSqD0I`U(Ots|Ug=IV?E zNsGzzVY{Am=}3TP%;Rp1k%;5&B1%UNpmadX$t0-VT-x--C*%9+fz_OLA;!T#Z1Wa@ zVeZ@M0awV_7=TIAzOq4H;}rL*N0N(&7~;0;Fq20OYB1I;DPW2A<9RQ@98*vUf(yuO zCT7|>afN_t#_VI>%xZV=sUrP$su^vT{J_xRiS9jkVH3^5TDQ)n5sTC+VsO!ZFIO|C zFGY-e=JL(>)l>?ZIRaT=2A(>WaKz_>i%Wr;XF366e@M@zsG8$zqNz*a`xwPFyBqIC@zv+vh93wjeHkSt^mfpu62@ag#!C zh_XxuICZCp1@YDY{P1qm^2_&P{dOzDj6|pTJFHPi(3v$13QU7OB0L0$cq%^E8$TN` zn3Gpbzem>qg=fAp*`itP{UW#|_Jra7?)In}&$b_f1z`A>Jg@esOmcoaHkQ1eLwlVL z_u?%&PrDnVs_vbz(*$c|g!<7bBD6LW@3?lp9IPfDtT8>kd9frz$hnb(YmGbwG+E4G zsD0{lM(-JR($!HBWb@pl)c#p_u(wou0O(_1-B~Ig$&%;1iAMX7OId=-zBF&2tWtE` zBihEn*RKf1O?L#pU3?oHp`st{3zsH0?3oF^eE)Nz_iJmQ+=$~lPSRg)Ac6qv?NZmY z2|9n8Hci&{2;ukXldlDReewCtRawwG5R*9k?YZYGG9AIoY+}IyvR~h5sc86!DZIUL zIi2}=L49sfD`OC!jvg_+RI19IW$jy`FqW#e85B^kXadkx z_Vqo-zX_rn8?0R&bD54d*eSfEuCncW|I9Z=HqdDi!n(RmPqal&wSWIf(Mo;PyKwb; zO42Xe{O^Z)wM0FatI*M64@wCzlNi;xMRmDIwH?@}gsOCpQ(<^_XkX_HsG8hOvKJP8-qHU1y(>ovs}3P z`RbROgfZtT>Eu{?&&vH+et++*E1hY>*_d;j*BN}c9FT9Ru3O_n2n){9UXu%Ul6z$6 zI+q%`BM(Z?mi|A9Z@7HnBJ4Q}rCWPQM^1%n{z&_^!C3|pO17I&=WlN*(Lfh$)CF95 z^%enq=4muABy~L1oL5@!bbgy)z_og$mwfHa=UCoL3`I?=<&O7KnWH=)XGF#x3*pE3 zdjz1O=wv&TU}R24VU!{-@J^oj>Dp7bzn(vgpOCn}mR>6@-g+RDBzf?8o+ysiK*Hf+ zxtX>+#IH6YoDno=y!oQYaMtby%?NODQ6<9+do0>BpoTnC_PCDj#FLCGsNf!a#9F5J zDY6aW``6A0o5pp`Jm74IqSODZsr2bZb%^fTn1mED3Ph?lKx#D0Gh6KG`6T1G3%?VI z=U1=1p(U^R|JeHquPC>Ef90Tnpv*AHfOMlEAxd|Mv=}r)3=KmH3@u7ZNq0+lB&0#= zNGc5?HFS4({`MT-d)GSN_r3qX@2=%?9TuJkW;}hS#Kd7VJNazie36sI-S(&}; z=3t&SdDfJ7h$`BvO zU#t}DF_6u?6px+n2%uZ6;^yhb#q=R5CP$0|mg<*mTaO36K16yLBYQqLv>o>elt^^} z#b?da-oW$CFRPs5Ja0t|sO~&!&A?BBrpT?IA5OYp%VFBe$A=@ftsY8|fu+w@IAJW+ zE`N0k%o3%g*$)})T!oQvtAEW9XODK$tr}(d_j{3{w*=SnxZ1NL^5;+RQvR_W=_q{? zVdgp|&F#XFDBY-DeV2epiIMA!O6ak?8Z2p@xH@ z837sY!1X}N85=OouseLF$!}WEg}3NV-x#PnR;#J z^uc~hz(+PBar^Ppp%(pOQJ4995^1o5w}u~yu8rnz`3#w{EbIZj#-TSj1)rN>k35OV zSdSi0S*HHE%nO|_IcWkS+}bw%6TR+S{oHT^oc9#4KOt&KSE9t6K-2O{3BfplZTt_v zbZ*zIS0urA{bzF&Zj?cP0R2}bqL%OvqGC3SCJ3}?B;+UK(hvF78|?X0e!FNz?Dsv> zdTvmWr-pCeONnMBLmUynU}m!x@nVTqe+6#iBiTdbEtF&k3!>4*Lf0*rl$9E#acjq& zF|M3oPH9yW;R7k_H2^FeSd>}?Fd)@sB)Pk)uG!zu+{B~x=%szPmG=F$=`rqT^zHT# z*GH_@?d+*Bce$E_<()Stt|DQ+Jxki97D~J{|~{v%x)z7Hka)d8wSNQfnwxXW(?Zc_SKcXIy~pM&)jQuk}op)w$2K{NZE4H!yA~&qLdYJ#e$k_{4zq5ai*CQ z`v0_D@8J*ZIG(Cs)r^2#h5qA@j|i@%dU^`$`2Bj}d%Y}D=&B}m=VXn=aIuqb?kCa^ ze^&Wg>Kw2=8>V7T-V%!i?*A2XsL(7Nh*CPzWs3$nMNF{PmPcSfORp4hFMcSd+zP(o z>}<2xol^JY%lB>(@lK2Y4b%4LabP+ZF*~z8d~=P^p^+0;1pQFyK?majqlDZCznJIg zp?_In6ZQ1t%LKZ#b2a*S+)*{{llwULw`h=?=Jf^c ziV)QokSaAt?RKwPlu=USPw*+k`ojDmS$?2m_XJ}#LO3et%S~lru zW+KDgJ}`JVZa)oO$#OqhcIIeN{Bp#WwN3|B9s?grdM~o))$P^%mBlwFBmutu(1$P6 zhAUt=E*2rl;$NP=h>S6cJkod80AQEi$7J@q};w z#gjFLx4IeyaDI`xVqj>AQ+~0D!K)c`Gyu8Lg=zPT~Xq$--sDU>{#r9rz zqi=;NJ<~KzF!4Y~bCo_@wYdvE`X6apngMOAHTZ$A|J@&nRl292de(LD^jf6;8S^A? zcVO=&gvGPoQ5nwY$4ZH>m;E?<1d*U`2TI8TIBoz#5>RuaxjgYpq2@>n9Ml1$+q94x z*Py<~wjcbA;ZI2k*bQX?uHfln*i~}pnIKjn5n_M;c)!m8^p)NWb?i--oVMA#MjGye z?*PdmHDY;hdhFyo;YW^B15~Z2&--g_9k0-+aMi3m@aDkbYMzVN^Nv#Hv&VuVlVs;| zCjqypSNJby;0@+8=et0)9Zo6ioIe?$F?d@;m&fhPWvIa_cvVj5RFUNmQHfNHKF%;I zaGdTdU^m|xcJmz^q`$qj6C`6`vCdBkv7)v6>#7%RlvjSw7Udi742dMMI5BF~A+;>k zreMz2W>(nxjxgyH2R#uAv*KQ1UPL+2g>Golvrl+Hca6|X3zY@jecB+=PU8FUsN)qM zo!k_^K!&`nM2bN>XU<1`2d3@&HZPCb#Lv+F>-IFAS#1FgilG{8D!D{zu_fe49+)hz zI-PB)cA`YmPEec!QP0R{f@|l_H(5@#JSA#v8to4Pz>etYr+TY_Ixs|^xAMBslMMzv zyEckeG?PupTmQ0JIFZDMF?0Yei5#&#n$;}w4}ZG`fJ$BnM={+E4yoMM?rGL(8V_ zQ`-9n*$jtC#F>nFU+ktW##Z#O_Ie$TyEq!z_$uKSa?3OXdT;l-fYy~%_6k?r!grXx z^U}>;oMuX9|0@(dsVsX^wIMD~#Gn=QUU!=zk9H-l_VsQ}HxUZ{Olv!icV$q$VK7na zD!45oWsN(c3EGVevkh|*rrt1;K3k}H3O28G#%X)@Qr=Jog-bh&C)xRM1;%D|iA%G~ z$IG>PK2|3$-5&>aa$f|mjUqK3`o$N*hz}7lSTWiYVIX4h%>Ue1J7rDk5 zsA_|9t?Q2$yo_$+(e;;m6_w+cNlR{kxVgld-oor(e2u|5WLq7WS7vTmm4wEKTZ_C2 zBr{dw4DRS*VdXnxdxV$^QXXs~e27TfHlSvG7lv>TzF)ERDf{zzuQah!8q#Il#-$KO@Y6a>BG=4fXfbh@q=9WM|x zP&sMftm9jslm3=Betqd9#E1dn}+kBQ!yP>N;->WN2(-r(BD`VtgC# z*bBE5(-=7sMnTLT`MU&Vf`QEQ`rhYGm6sQ%H9&hmo)(ZRCiC!gtu&mH+u-%2`Zsah zS>RK7MeBWLzwl#AU>LNXW7}wYP~>ops|c@?u3qJJG3bQXhA@&fNoTljhY4~x|5zI- z9oI5TnLnf#SOIZj&EDDrl<8x#aJ{+1s0mP|_ISrhV357yP>2sL!ISiH{7f?1J+Jfq zAp{%Nh;uA<1Uj1oskP5rKXP?l#+|%io*PqN-!_e3xU==D?7lzi;-5tG@HD=x)e{GZ zP4(w0zUe87Q6ipAbsg0FY~WMppD#7a^{RV%g}K;;;voVq5?j|)r_n@hkRS%K7VWnZ zNyT`uM#!$w2Volr@>7nR9;~*`WA<|OId_asfoOgZV0rglsAdbg_%NOHx?qYnzj2ba zDP9aCBA@R~9#we1X$MzBt+Yp1`FA`K<2H(@YAJwNX?dUTdnPRX$PGVyS~u`a@%}5z zLVVuz=->*sX&aLoGwag&TI34-UTf->3*=b+!keLQmY*Z(lK@HA@{8e ziPJ$H+kID(jYVOaq3z^QKb&<%uDXZ(VaBxctle8>=OA?+>nVMi61&1KHy$H_$r=D_ z`R}$$o(@j=(OA6=?{fn9Kfj-+fb){8*9+L1sJxxuCOm>eiVT4Iy3Q15nMIW1 zULG5jo&?uMk41z6GN1dl<~tkuYnZFo;}=<+F2Mv3qo1o-Ff3#@)NQv?o*ODzGH}Yb z9yQfE2N>-R()F4;MIh?jm}N!ng^_unm*cnhu6kPxM>6_W;m2qB)6wwQEZzK~yX^*m z^jeKQfVzsaqHh&7fQJdQRPF=O_}E$lue#*XCFmfy%7}Xgm0BquSw^QB8{mB)C`;&V z8@?m`IgDHEJJyL8f9CIp=#utvjyy_mwA4zc9u)0QYyqso5_t`B`nY9KkD#pd=@8Fv zLH}Q0KCQvE+^+UqUxlgUBV%%A0bAPl}573Jv%D&oKxTE+bQ0VM9B!Y*32CX9_p^?Wu+8?}h zr*9aG6a_v{)Dnu*b&z+N_Ja%U&Y(N)R|?2H0X2z}_t`A%xtXp2@C}y0spz>MM3lOc zE~1+U<&VS6No>Q=EzRyZt~7EV9s&Y2Ag*z`DWFYn&{p~>?re+(V#J++Up0k8E8O7j z{d2okjG(%O51&zqK+#7)HiFFf)E7s)?j>TJRhc8;+oa&uelN zG{F>h$fNJ%Znm^jbJbe#@)!UJLd<)yD`~N)NxZ*#m_fx()2G!pH+aeH0mnFrNNNCcO3?_mS=}c;w-0Xh-p7H6?I*E*-Jf~^&BVS@XY`k zw>&f0VNd%S@F}HO(YC9(F!zRK6`=mZrV#&oQ=HGGKD+nNV&W+w?w`-nMNQgCxw={Y zP|{6d>R0agU@p+Ltc>yP2=rHajk1@O2s1O0=|Zo{*!`$;cX0tl42J%KH&`O+59O^o zkVf1i`T)(gDQa#5Xb|Pbj-A<0MfE#xY@3mvd)kP?-=lY%y+GOF-X}OY>9MQKWh3=e z<_^|0V1{FUfDEL;nnJkF2#WlsmVkfE0sZlDyaxb>__l9+ucmrScaHVKJPEJ z;qP(<;nMH@a;=Gc?yPl&2yctdhVW9+Jj!Y~Qvw<$%?pVKs(U1X}2lp2A>j@4zoeCTA;{_z(es}L_L?FY#D}f3J03QU^n<7CHvkc;BdF1Fg9P7bH;AdfHYjWkZ5%>8505@ss>rOZYwRg*peXi z&s~c7ArUKHL?hT`vznr~iZJu%Vt1dDBL!M1><>UXIVP}MLw4R#c^xf*5o`|*-3G>3 z198sK+4!;oDyO(@wtWKR8kL(jagm}1S9(Vq=_WYr2ID(J zi&G|Pwh)OXj+L&_3bW(pBqo|Fp5`AcDm#=U7xdAOACm2lhH5-(mL_i`z5qUnIf&1! zAmvq294it1SrbgHn1jfKG&GrxbaS-)6TEx+K55@Wse2+%7)n|pcj#a7HqA1MKonpH zz%4e#H)0IqI(U54a-d^d_p|M-02W%l4-C7`U)(`ST*pRbFDUhqUfO?7fG$vK;QH=0 zLb4;rd-T0I)=wXQ28L*~ZKB;@WO}dEEFqSzHkpR3087sBB-MdLQZogtkd`MikT2Pr<18{v0fxRFg zF(|zZb3rxN8G2g|dGG(!7%!~ZSn)1N6B|%ZeFEO^1=JY{Tz&`VMVHXCtcJD8hK9|w zk!00$Pk=28)w;@szT}EG_Vc5u&uV+Q;v+exR*W80A)P%kSFYxVnWIhDScWtSoJ_)UXwyXL!gY_lw z;4X`@GxoP)$u#ke&*uOv2%C1pN*BbFgEabHQcHd1!jttYu}1a}0hGT@Lwxy0QJ)&p z`qf;7+)3A`f{MgbfU+zP0*^FHfG0=`sTe@BpOG`jzn_@<;7^MmNkEG9|g*5VrenjU2ggihd1=^ z`Ru*X8-8#^ypH`_0xPs#TR-lok~%Wxc9OY2+`RQchT7zIE2>Rq_hIl+!j>DTtiSR0 z`=wVykRFGCNI!Y5**CY0rng&QUK&StN znKN>5<_ciIXOYMY<<1f0NRy!C>JMyzk}$sJ;R-bzE4fi7$Vw{3c!uwXG>o^Hgc6?v z8P@I_^IDap+^#am;luB&X=on-96nzbz(0ITY2?El4NOuRYv~5`-k|%83{lKN_9>_) z_Gt*VADH_;t&tA6g_yeS)?IOa5JXN19iI&s->5UeICr;Evdvq!+}0@TBJ?EL1ge2% zdK^aTzw0+yJ@g!n(5t*jbpjv0tBmGfz>BKQ>%n~%c)?+ip23u=66lUYq zVR=U3wa;%=H3yPjJ^N@>j!!8~1*Qks4CJX*OH2Fky)jY`_=|BTOn75S!xp`i5kLj= zwvL1#T#CM|{K*m(47{z;IutnD9EJ=bk9$Rd@X`es_)jkagLlSjEp{oV1&nOjKj8Fz-1g9Yx0L0Il z_vf!agpfAv@J9Q_Y!&YBVLR@fm^V0Z#>|{otKS|7!a#t1b%kEo)9bfuxM@)7(cCIA*?MXp{_TXm1YW^lZ21ygKj;=3Ds8>0b(EQ|R->CgVR2;635TiE_c5G$${ zvdAm)f|r0m$LZ(Gx^MQyEo8e5(moZgQLO+vcLKO;pBdw;TPToj5l5XL(wVY0n-sZd z?AJ$~IgXn?u%3)ENr#94om)V>P?-k~YQ`7;(Onz#h3tR_KpsvFWN+Bzje~h<5S9=K<*L78PVVE$ETUF|8+@ycVaL-sKuC-5#kdh13~17;{wZ5fm!4 zzU9MLd!3kO&HCr}#VkI1!>w;l-AbJoGcb^c#|5tf4SI@1`VX zP?GMt7~Xo7co{ubDSyWvXPqNIYkH;f-@nX2i4Is^_Ts^P)#p6FV+1~p1TSJF+`$xt zi66SmG6O8Vg}z5MTh@0sDXdb%Qcd_`1t!a$!``_@}*qJK)ht^vS@uUglt zB<5D@>H$_q-G=MiyR{P{aA!~{EEs!~t65Szp`DDJ6%HVt47qOZt=ZlLo6*PRu=plS zoW^`hiRMOooVMlNwqdF;3-(r09hYjp$6^St}o1nEI zV5GGQ!!|en{w#C;eU_afURwW;vrGv}4DY!YpKwsM`^xd$UxQP&3PbQ@o9Q0>U1Is{ zK;BE#L}bzIks(s+&kuA0SW&)p_~uY;vqvI^4HqY?2wzMwvh9s}tHI152xqez;S%N; zaQPs%p~{a_5e+M&+mk87e0-jp*`)W`zy}^#QX(5k|4KH!i*~IFK~EIbXd=8U@ge*v z_6+KO%W@s9&Tb8U$@5L8c^CxQ(AyHMdfq^fB4&FRHixPv;+h2hXD5JJmcvOH=XzFB zYIW_u!EepH!d+JqFfVAWO8(Mj9DIvfh_rS^@uL$QD!dQlx&*JwxzAPeX1B{(FaOL}?c=5PP~d;jmvP)2@Lw9=Mm@5|@k{~;RZC3Ej%nXbvd zeEwjM^n9M9^igy8c95MyIshXIPC=zKuE1U}7pv>=J({sx@o(}eofMn*`+vNhc%~51 zefyu7;%}c5;v+1e^TPahEaE8}HjTg&1*p0H1wzDNfon!X(WQb{^3RWc|M$PC zQ{Jb56*M!;X8c_SkWKQrssfF)cY~=srgsrdVyW!P~ZLZ%6?|$>EBPrZ^2E%8OO~g zEhQ%GcYef20UNSNUfj<4^{U3PU-EncPqlehOY$4w_1mU;dJPv8JvSc6tNr%WJnSkC zy*jvO|LgPr-&Xyi_3ab#-2H6SO%iSQk}g;|=zK7ZjIkr9ER{tea<| zGX}+92_$ttUz}(ojl?dFkcWp2m*ZHn&t_}tE8sX{twQ^(W9;4b`sBvJRKMjxpkJ-r z?G|2~c`}~NZTKch*rgByKvTV3l@y25My{f|gT$<^L{ayO(@pQo)$2s$Q&=k>&9lDE zaFLxrU>|AIZSXqR-JGancPog+Pxd$hKXHA+ZS{T{T#=*LS9m6nkt(fZl>U8r{ZEy5 zF(lADS{(UvYb&~^>nK&xgNW={)>hP5?yHTl5n%iBD##$ONE9gZKP71G2Sdnql>l5; z)4c8S$wz$_D&Ijoz6(!1E}t;f$n-2Y@cOd#ER$CzT?l`m!|`c}Z>j5Bl73|K; z8BhdNXUA%{hf?siVnOlSb*7Hjy9tl6s#nBo8bq9j7O=rIDW4$baZ3g&EtO|5whikn zD#=S(-T>wK@>4@!)b<(BWl#d-ChmAPUZ7+-Cuu=c4lhu`iuwIOPlf-Hx+CU!k*D#; z`DLJPcfxx4xV%`?JW5usF5rfB3~fsPE(al*MXcG&DHbDt;?;_LV^0;@0h%t@o>xHO3Z44EcaA z#8S#Nz&J1lX!dAr6}P>m=`fLi2qs;-ha6ETOw$Z(@KcKV+CF-gFB zB3_A=gQvdPFR5TFV@}y?hN)J8USlwT2S`;aM@*AqND-nb$xM64zy~^ZH#d2v&gc-R zbKO~pt3O}5G@Pcu&5EiQ62nejf6E2!jt%e~6BFM*ajzHZ2)405R|wLSDvq71gOO{?|StV0!xHuj`oTdgEE9l=B0j8kc76^Qfk9z zCHz&5M-xNF7HRB#^$V-HrOlr{C-?V(7odedFyna2u{`)cNa|i~ESR9}AhrFgZvct} z@IFj+3PhJ=?REpi&%R;_MKK?I!R^n%?_ouwjtiaJG#+N%$;*dD#jSTXLU_B`YOX+4 z8-TUua6-68a4|V^1s~DieTtbpaSQ+;&b6q%*Lx*=3Ljj(W^Y1@<$=L5Y4Ob?hnR;M z#9Y2uF18LMCyM!Rbqp!wG2?sAN|TSJ_=3>aGxIe-2QnWf73}W8ls8p8%)&}p*3C}~lN&tz}0P|L@dgT0%h(WO3 zebucnQRU(JIVCYBW6v#JXC_v$fX8eF(8Co!BK@jmsha|)z8+gw8c}H5nXcf8YDg^^iKirw#vE~{p`0!K${*k0tIs)`hSU2 zdl|5eP&2}c*sWOSv@RHgTy?JSB_L2MEm?+GhprA09u^w)U9o_J^{O2 zN`XvmBD<26FkoioT!7u|;gE?FHI$7Vl)4@7N=^Ux!~#WSBs{ei*I9B}SwG76G=3CQ zz%fe`lRL_}Z1HAlRK;~wNl)7g#CXkA6I3Z7Vfk@bcfT0FzV(Gm_TZhO%a*5;GU;zD)oYSSOaIE`n5j!#&t0Cb7Y*pnqhTw;Sn?SYY0{p;s z*g?Md`B;fYB_Qk;!oKRb0IbciVYdDZ40Coqob+x05c%d97Um+h7%EKB0qE1Y3-0{i zoFt8>78d8K!fJOSii#R8zUUbG-PQ%8+jPO;M-PwLLNknkkC}ZegPDa+RXz}1U|lm< zvCg(dF|yPvjFP`Qc&gg#^5T3Pq!KQE#|5QB@T;9}1!4fPzo?FIHKAo%+loE|oXr;? z0O}!JpRNRM(`o>Z@@|)WI0QoqT(H4lsOg6TIMUbx;j9`6_B5j$Y2DX&yhSMSZr+)j zA}a^K+^8Oai#I@hVLx8u;!?9&Un6b|bVy+)QN@g50*wV_{R$VtmpQ6w8>XG{(?52D z_0JmPC=30}-&rwNP*^NbF z$0%UN=AypiVdL*)1+dmvflNDppdsW{O~~va4?Dq{h&Ql4Ob|m93-cpy_3wgJKKU}5 zqf9we?YOABBz`*5GX|{LiKkt03WFn9NdN&IC8{g}-y z0Z7ZoJDs@jkcxMF><`;HoQ@*oXzU04RK<>)E0qU&fH`Im1+q4$_M|}Cme%wYVKB*f z48;Ep8n-3-Nis;cBp&q~=B2lUzxRNm%;{G4#PbF~{Goax4#YWFDc)E);M-@58kP_n z77g^Kmf7OF15xlc$}s9Jqqsojdof0ly5UtaM})2?;q0?Q4;HGO1inPCXs?iqkQ3=s zU7JtQ5=jm!DLG18a+gnBv${91G^HDLT&mFuhpYAz&y1Uyo4J#$UITco_nIS)v}h^e z4OOVV)gQFj0l)QJNDpb6XOp0SI~`m8+yDj!c%;xz8cJU_eF)FvX*~kN##i`h-Ig+f z&TIC6hL~vHX14VEki>JXks-wSEuU}ko6!49ic8N+G|RY5ly6+X7-t zu}QF-y16%WKDubF#s1zLf>}G&97(>|7*V34uPC@sZw@Ley(NbM!dAjH;gh8-_^AF9 zYQ)l9{LQ}YVXVCm;W~eNk}o2yEHs+A_1>7yTn+0dW18%7Rn7i)>%r?DD+fPR#n)Gb zQN$j3Ss_t*tG>3gBI>Hs7g@Swb$B1BM1a7uevJbw6(|Ul7H{H-rdT08#0^QSo@6QN zUlCoNqKR_9H%jQ+{lO8dnLX^ZOJDy=p8K3LQ@yk5!KlUpB_=kKw$J^d$_(zSZ>|4a zLGMF|C?Mm#&Ll4zJ#mqcRsvwN^CERxnDje%sfAhVgqjO{j(33i_mIE8h%Hfdt7^+? zFed8UjoA{!S-jmZ)>d9*=v@Xplyj+qzV;=XSVLWd2JIzBP;bYOJ|4f>IbcbWZz3j8;U)bFM^WQ*6 z-5|~01yDC^b7i^)ff{=;=UvXuZ4a4JFr5N5V~CYhoPJmJ>Nmawfoao^UzzW^I3$^& zQJGh!A7ofn5vDym%KCg!pmDG5olP)H)mqZ^ovTGlTT`3WmIc5Y{RA*}O*g46f?P>UL88;iHS6l|(6_ol7z-1zviKmT|@7L}1hdIZHv3~L! zVx@&H(0RPOgL-7h>w3-JIhkj9;jcf4txJM~h|4C)X#$}4S}3GwSy<>(bHr~J^uB^! zmfa?Yq~xv>7f~N%hZJ-J^)d^p6_odbGOtiHtWDf&!cK-qThk^mRuE5gVFw|Gk*)4~ zqO7TCBcs$0F&3?yW#OMqIY=uLm7if?56*uUdCij(GfaVBg3Hr5Bg*a_1()eMWAI&_ zmIF9_E{6$Md-$Z^*eBn43xl`A;r8rrTJq=xK8*PyQDKJt^PtA7tvXQkK6xJX<3>S~ zvWm(Plsa5(B1k&9&lHU0|6V+MKdk80-{Ha|7#l8hd|JH%(#9^6?HUPenggL;jz9`D zElOv!yfqQ)-k``?%><|3=rE6)0I7VeVvF$5AS5k{g>oE-^byI_smRG?eYV{*L;Gb8 zXI+Ye7_HWd>^V7fPmk{&&{q_DDi=FNILF9$;Lpy6xL;*S-Kk}A(}%ctR29V6-?K`h zMzF5C7tc2~8k1a~KLHx-GG%2k*ZQx!Z@9S#Ez+V!hd9^;xjzC^60k_^M)iVH=2CZT z=43g4`vyjN^a@LJGsWTeGTRW!DtOnS2L~q+3g+X+@OKq`cQac3p8>&Vln&IksJX0X z|Ei*;uvIj!KB%Il?Rll-nj_IqI0hhH3{q1qj0gn?H3Rp834Q8EC0y#;f6dTGgE{+5 zZa~UVr}3c|N%bZ&4=Z65f*l?v^`|J6g?dH;Z+lwZm6IDuk*Mt$>0guOQ>W@tu2(~FES_lZIBT|Aj z->!ox$%Lx=Mtm|a=ipq-UDAAb)6meWq~U}!enr@ec)RPWK7qs#rYTXP!st){fOIXg zpF+Z($A06&9SU5+PeMYRb{k3Tt=XLK#!1vX+va^NpO(>UCi9k!sjMpQD~mw0<9!-R z=&~Q;1vG9do5m_kC`mS5SumR>@z4R+6z$W}LGk!F7cqSsqI!f*Fv+}v;IZK4ZZ|s0 zOh(1zcW?`D`RGPH6u`)Qk>>|J)-@&s_6WxQZgMcX>l)2 z?*!c|*7MrvT;;6#Io?r%(W@f;^uu3IIShL_8K^$2XBX1r8qQox-7CG*cmhTzA2kJ0 z9=~?cBkw~fr;3c^hFdYP5f=>a$o&czRi?V0NMZFtj~vxZ@upp7lo09;ii!&Qi4NB! zQjy2=6;cU)p>N~E=Y)He@*IEt=CKN`^ktxidcV}2kpMRSvS%yS^!wN7*-^~6vcyh_|ikO(#G9Z3p`UKjpcN{7L&gj z?G_xTx;r#J-k~*P0#f(<&hMuCc94B<`d??|3bAAf`M1Dg} zdy(t3C+@x-Wfb@cQ%}UhpOS`WWov7TE7lP3w`%W6VkZd9iq0re%84s_%Lvkoh3H8U zc05Fqv78q-;;(Z#g^RuRGOqJ?Xf)0-!X34Hi)Z-2E3=a)2RWwfYO4E~TIRKS;8aok zwh?IZdP`m^c&j}bA>8FWLwu`y7sJ}Bzx7)5oY5r38N!9NH0BYD+3XlZzJ3n_LB{Y- zWPJb#v{a)HRv3|F8-y0_TgJhaCha7Lx28Q4{V-In(az$MA_~jFf@!tILB)G*V;$Vn zv8O!b+?;+lo#4SR&QogHi&A%qR%hL)5^0Kz24fDhsHH06S+BTLzK!rIjSqSmC}x{L zZzzP4@kq}5_BOGZ(GJ0jYHwH zvc8jZ*FJq1A@5-2JZj^;)k@867@4R91Y;=@1)`Ozss#tXbCwdTj36ehcEDPm{6ewb z;crC}64p(stL=4={nU2v4SpXVS6j>70!g7Gnl-sU5d>+NgT2}+S<5f&-bp?E@(4f0 zYkbN+*iK5iGm!48S~r;OK}Pa39*@2GKK9ZLwB^EP?QoOTLw~jyxVsvm{vZQqV-1um zTN){-=lkxnp#>U|o=C4UmCZqusX0M5jeNlou(fisT6CC;WyP<#ij>FgCR5#(EM5P4 z-L@PH#~iJ+xY;8pyD;SW+g}ugcxJi@Wt(LJ^9@M5becubP4gyV6Yg2Z=3KGRt8`@2 zOz)mv>7$e4L_FMO5HEWu=|^BDkSZ`;EnLfDRF1VCRylTp@hvOhr{UEv5MBM6c6nxY zdCK2#914Fv-0c8F5k(~1rDzt<#NGh67}<2xv?j%q9lKF51qf)>;p=F|kU?n?Q%3wo zG(mUAQ7<7c*BbQcGdL8=lhByozaPE&bOEXzKy$Kw;=wS+c**TMj~&o(Npn$p(p&*B zov~nRYi~9qNuUCS6{}?Ur{k*z+2z#nO1|}b%l(><;;NBu60)tuGZF8xOrkIJkuL=Q zFDOf62Mb=b_Qkt8o8rZYLV@jTn2v-Vd}+4Dz%gm*qsLlp{mqoqf?5p$Z(t{N94182 zpdjf?PpbKwTvL1EXzxdT1ub~chwG1=Na^{bu6=&CYCU)&B^ban)U?XI?q-h92F0h( z&)zhnIOZTj&>AjmdL0ULeJOGLXjXCK8fJ+-%aa>Pz5?~Y1K9b2#a6wQ`kxXt1Fy`s zIW6o%Pl-<5M(IXN%}1t0WHi;qrh3RZ9u80G!H7H2{wAF=TI?;6Ct9t1a}+e9%kBmS zQRi!Jb|z+oQzsRxq5ogeXUnUstCgb_8kjXHUH%wB3 zCdKaCfk2j5v=E|mNN&_=H>Tj(X>h(t&rH-o!aSm-9X3t(xfx?6P-s%KFB^Tkb=fdM zo&*xB9Z+qP3?%snjCws~hMS|6Eq#mHG4!mklxm%szJQ9YI<3l}xLXA@dQ#v>1!g+v<2yO4N7G{anw(C*tVuWQS*kv5uDpa1ij{ z>*X}T79A}F>|;r#?`bPO_&pZb|GAe8+4%{UPx2Wulg+)0A#^A|MTM_P(& zAq%{g85-GGJJ+K9U|7e_PJ5X03CD}{t`1w72zzIMK)c&^sd33>2wdSozj$G3m{9ew z8&*yYI|Q2GT8rtgcP-KI$G*~H^qF!;&_}p-6&ylb0^6f;KOwe`x5!*LP5cBHT61)_ zN+99mFjkd4DW_(oKpttrgzX*v0kF(>?5e}SnCfkrQISpNVKRHKW%y%zpR8s+B6?-tuYCrR# zjEXv6;{%N#HwBR$0t(1DeaV!Gu+v=?V`r%f&mP%f7}xI3+ue?n~PiLr(xV4 zg)esTt}`g*d`-G9brtsyt%89ajWwrW(ePKyL0s(#Jr*-oqw2owE%}}AW4Y$Z%zwap zS$hNeh_zCbg8w*GC@9rhCCua)y+M?tWOO&cZzw$JN%JGXX_2+9Tqi%*PChh?Eig+C zV%3p}G|j$Irl{;91}$jeUFKa|C14j)Ywj);dmHpdNg|k6Lqn#>b%73!QkJl1HqraB>O0;`oY$6+LLvqyRqYaU+ zVeI9%V2`oKs!+a$T*bfCk-X?V4J`b@1%Igk+?_W5QFx;lgPXXTrM@-00#8Ip?N_8% za&h97)Xm~NJHd@3sfrO%Ix36jGp(U>@IxOZ^&l07TSX=`TLi%bm4k2{L_}Li(9BMv zUE{@{@vm4y*_-MgpsaPm&VYF#u78MB2cD28n(*d^FY@iO^#IC(2BR z^HT=k%9ic-TYinaN&krzckw7%9!qjfyoD@Jf5n@Y9Y81e9WmX@FNU|X42PzgH7M`t z<_|FvvM!fC^>H3RqR0z_I?3KLGt;t(_MHq_g z>o&>=%%)OmlR0Y=cpe&YEkpxQd6` zhDTW86^KLW1+RX}&7SW&qNE2hesAO#e_S%T_CBuie|@v5X+_m*2ex^W=Pm~ZVVTmU ztq&QZvuTPqaB7CiG2Phau+b80T74dnr>Ir~!02%Rb${vgjocD|?a)=ozWP_@(xFY_ zEAE=Pb7*m#G#K}+kX(*??!-{l`lfy`FIO%7X7@Pi0pPZCZ6sd9Y^`CwwAZ3X*7pL zV{(cxR`Fez;AR~~GCZW~8vROKEv$Z6-R)gPU99sdQJo^3QMbZwMl2LLIydpTNIvN` zd4)KB@!e8#)JSIn@A>&1lysyYO!b|-S%1}o5bx393aaA>z@e05b5kntoPhx-BDCZ} zugqaZ6Y{PRw(cK2WBk&}yDDabkCpDh4ewNKh8JFsnAiT5jJC9vLmk?D?PPkV&qD~l zE!$RW1Q%W*aS1oD?v>Kx%x$tgpZTm@SLx;%2>@AaZ?DQgVS>he|i*9!G3j?T|ilQQW z>U;Fn;O$6a+e|Ic{pQxamLBk_V(fkk8#)4DtwSnn6mY0M02kb?Ypx{DLPzQBrdsHZ z!@#tk5f^atqyQo(@hgsxX)-gxJ%K@AUMs$60+~sBQ;=uEr<0o$y=pDh6|kqMC7XZD zR4UDZuq^3Qw<*+|@hR4p(qw$Pi8g)w;!R5G6zTw6G8WgQBT9Coj9pK)8j<+kN1lk~ zm5OCB{vXn8Zw;;!0ydZ-_G#5RF~?3?`D$~xknMh|fPvqQvX73Y3u-S$o6Y;Y6KiB~9ICO$=)# z46ngwXbLjMa;>Sncaivc+nq_q3k7@|+V&{oY4RUcj*Y8yCvKPLhjmlb5zZOvYiOQ= zaH84wMb8# zfb#~pYH#~Aq1FpS53smYYsZmG5ytrG=K?XWZa&0`=%PjGhz zM=@vk3w9jjsl23;Orv?6bx3oS;9c?auLPG0>z_D=^HCMlX$M;7)oe^R<%hcZ#d6Dw z@DD9I;$L;ki0w3WwwlVrmI_4McKJ|G%(Z4(w!vLUJ3VQdu0aG*rb>?)5zz@?aODWr zpWwXw9CUVm5_KY#s*>q?zo`=#dNZ*nN$u=Q)i3R0IT-Fz!-KcF4Fn>tt{G0i^XiU| zpAV@rz&8XFke6!Tkb7^1UqU`@F>sPfns~b2_J^G#@+5>kv?ycwN${@cNl5I6%aKO18kU+aj{>m!r}| zVhddp2icyc)n1B(WkKG>%iXM*%E+dA4o^?bv>iXQQw!u4gO$39PeqKp@5}hz>GV-Lq~LM)HJ-9&(D4;LoUh`ecI*`IhQ5B+wXo}pFo3lrgwcP=V2`dS(i7ag>I%6=ugFMi+w!6r&JQk+*6K!zg%JSUbbr3UB>LWXhY0=V+t=1P*(zzdPt0 zVoA(3zN9vCD}Q_K;X}{0thMx2Ao*eB%jQVZLR4Faz>GDEaXzr2)vwPpi+4Ca z-%QZ-84g&z&DdM9IyD_y0kyww(MZ{#^#cDz*p8VY+(Az`phv1F7^eTwOiV)|{T#p^ z!Xg<)$L)WL=S}Mie4Gko46_4n;_`LNouI#>UJAqyG!I*VE5)kM1MLjn(Gjqhca!Pp zKM|kb|LK2J*S}>3i-WXI759oXFEFHTF?a0iyp_OY>YIQ0AyYL)_qD3Yi~F%URCF#&DLBDO}+u9T`N_N^3! zKvg84>t3`w5F=na3fh1-NLx`^*l`%MQ<4lHF#ex(N|9zCfw5CvnUi%_>zW?3G+DD?2iw=O^9{2rFjW3 zQ6MR6hmGtT=RfS0Sob&(o5RHM!yiQRZ8wd|v)FSB-r(iof-MS&e{U?7e3+6Q!d|); z)BN%8a^_ZtB0&GY6%2m~q=Ogj@!6QZqzw5<=6{oN0Zc|FL$GXP%bIJ+*s>-oEjyY} zUGfAg@59O*G?d@@r_8&=9tfsMoVLLA_j>rzHq!r(z4s31x()w_<5r0jm7P^0^MjI^ z6$u%Yy(u9fd#{#NQD$UhL|Mt+k|=vcnML;Ao9Dbfy6>C&_x(P{@f^qV=kNZb!~IV0 z_chMzJkRSKub0kickai7LIXr=3-HYK^@zHQE+{}T%77cuOMM<5qSpe=g>B+{-{V#R z-R5^j=xY2T78@PYWn3PA>Ay`NvHhT&)A^m zMWYt#WK~6Yo?Y88#7Lcm4)A^FXfyg7>hm~i<#JpN&U=fkzlpT4My-kDyg<@j(TbcX_ENe#hYCK7T@XuLl1jOP*WN@ICJZQL4c>alp*Vhj}tZJv24zcE6 zCi`_&0I$+#;bLr^C-=Dizh4lyIDXeG)Us^xqwj#02$;Ke+=pLvi zpr+Pi;!z5q2+AY#vKOfGH+8#(e@gEMYfjmh>q`|Y32u$n884Kh<9=zzTu&7fI*gH{ zITCQR3aipQtZ2=)gdK zviT_`OT0Uy1#TsSQ7!+u4l7Y3!GG$i%(``l`v}WN% zBH6)55)#K%(*V`0cV4ljwl}+cGLgz)V>ZC!s?d2WI*gS0+jU0nt1Y#iCb6Md5V&ES z=QpE)`@4EBPyI`|<=Ic76^weQYzb;7-hU^CQxRzrX5?m2C)bqx2(tyAJxYmt_!dLq zlJjd3!xP1~8Q28@_^x<3gR7fSe1G*Vl7`?@O}R4zl8R)~W7$pxspQx=(vCH_ZVy2s zV455pYK)0-D40q~FRbZ^F zJ>5E3wCHlTaf{u+Gorl2s4&J-lXTZ~s8;zPUgoQRNF3krtE*c+IGM!rtQ6K)*SDaj z&1IGlH{pE@X#LRmQuSgIpVLa8$CI5Z^4w%%G}0~a=ba}hJd`HrFg0<}r*rY=<1o!R zHrCLrn=8eD8r=gKPVGRT-Bgsz^EH_beb%ucQNPyjdNqxMbxH71mH$8xUd|J{41k`FQ)8T z(`yqt+0yeX=w6&>@%OdsX6E^dN7$+{md_)n_m#KyIi2b9M#z+z-&_BL^#-A7+wF~E z(bchPweGCpEb9do?bDF@C6BpYE2Yla%Cz-739fOkFx%j}-3)S$NOa2`7J^7LmGKNS z9Ys7;DZO^b{e~*jyM#MS`LmXU6GGsZ~VL87tmvAwxO+!>ZKUS{Z1Wx<&-T-7uru|gK@oE0FhHe8nTT_+IDAd=N zDB+W+DL?eS@_@WXwF+97hooo>Xbtg&^B5*Bh1bh{=AXW9dY|C9V1jS1EQv{%oLP$> zv#D0U&@IbfS!ud>o%JflT5!o71-P%T%(vdJk*TGBfBY+r1mmTiJz2+UILpkuF|c1W zT4%N{jIpVzb@5D?cK@ZblCkn7WzZnI>Ey$B)s^Nl;P}SD?0@o?eUF`*$CbBs7tGwmZ7;o)e#m$0OW-4>6C^JYICuRkfpgQp z{kY6E($T%f?BzZyfT5VXUof-gYHUq@^IVnIwWFPhZ>V1j(l!m?RW>_TZZ@=Z*z^Xo z+~@{6nayw@qBjsZ8uyDK*pQdJGw0&c_tUwPzR^KTLNZGJXQO9nQyz1*i;r|eGb@ug zw}r$PezSIVz0ehfA3Qe~aV7OnN>iZpJ>6fJoVM#CWyH6$SP4@I>5HEXM7Ay6GSYk^ z*43EIP^T;f&3mSVg-bG zYudiHgn`!U?Tzv&;|l&C4rYxYwHp0Kzh=JjuR(3y+)a})ft&3kzcE75JPm%gQ%{gh zCQVYf`H7Vrdv6?(O}^7ejz#yyhvJlyLg-w< zobJ=C{tRMnr&1wuTV00N2N*Ej;9s(TFOJzc!R~U& zbD>%mv(dC)ZP;0xwxFW<08?5wWNI?^WTofoExra49*v zXZ#O!#GUGZTWCkwZz&VcWjQ>jC5cyab&Io=kM`Uzv0r%WG|O`ygHJ8+7r5pSq7+1ViZs zaaMCawlnlR3AE?DaDMHZjqfEt)ie~rbW9T{3`&&3zVhX=3z%~RS(`ZYhu*;?Zjie4 z7&e|xlUYnFm=lnXH6OjdiTE_uMf+cU3)jBn~)vSl`Wk^2Li%E4q zcEs0$#uB$K+1|%wLu`P=C1=Hcnery(I`V~<$16h)>D^9j`;oeM=7igGg|WoXUhel7 znx|UJ=>9N3QNft5v3xyW15n>$Deh$3R3!7PUh5PoM zZIY1`SJtg3_fFU}-DL0mQhlM)+YFjls@#jKDJVY;hz#!M7Crd_Z!kMc`@!6!=N{P~ zFSJ+4F&}3megh8Yg-Lss0jZXk83Dg3*yVl@bcIMvbAJdesrsIm4=!&K^#jh~V zoFm>HN08UaMDU)9WSQe?q2cw@Wt5k=bYGhrbfJ!t^~YSVhQ7pSulrtKH*BeJYXZRa z>7Z|A9vU{-J4vnSxKLvED>_QrBl1zl`LqVY6*0PkLR8n&vCn z`haYgt?O$MhU2H4ZUz;9&4bumr($>J@X7ZEQu`my2@{G3M}C8BDOAJ<^()I3&|h6s zu51ccT+@i=4W9}Bs?a7+?X8pt9XHL4tQwuhE~P;blu}v~9XoiO+A*};F|?HVYwE=S zm&>7NbPe*K4Ci~CzsdekJ!aO?B=}P9xm+KGh(iIb4kXEHSo9s;`D>$OyOjhENwO|3 zFH6&q*AvP3>!b7c5!7f16Zc%&dEc;#K;o&y6vE!K4dXq+C>BwIy zq#0IFMlt!wM}6W|zTz08-Iq?LPP|Bv+d_xw!Yo%X49#JX9ol3~Ako24!Mij)BNFUsLoky8ss z65{+Ku|!hp59vkk1e;fUj68RlBABfqX?rk;$EQ4;lsr!LE(%^ZIoQygYw`K+2yhPq z&FuYWtB4FljjO9sjPEV3`S+H_PREmt5%?~Yq8~$iEqx*=$|U!9Ru%-?o{px2d{|II zlKj3q*7~0U*xgE^9{5ZG^o)bg$@(kIr(`6)`K~N0V|=TV8OcvlA;h547v{2-)JovZ~N!Y##Q`-5TZb`5NAl1?-o^XeGM!@`{ z!B;w9}&p{$oHk@ypIB!f~+hH^1mdLOn*W+AKj?!@VR{`Pl+;FHE~vzEMO!n4GoywT0Bm_ zihIg?4Ifv!_+uvSzQy+xUKctp6+e>JlC)=H(iaL6P1TW!xOGEzm2Ii;b95L}DSb&u z13G*i(Ez_R?Jvmdqe61ih?LaE!X#J`j}AXq;#xG#rI(XGvXYh=uWT_}}Y;PLKH1!Zoq8?`S_}#h(_g)=34(%!aH~S?RLI>9%WZ-*LSflx& z)v-A7C){MTjR1?NC(7Wv#H0{gpP86IosoLgGybBNMj~EkWza13Xe|3<36mOnHqW0L zSxU21zp6CI#5uYtv>peUCAJwf z1ZV6co4-i*LylEQQGo?ZKFB!2yUhXyidCvtkDEb&9s@Ur(fT6W!!+^JuflrTJuBx+IVS4KUtU zBAh>-O9fOhk>WauzO;*q@0M5lNr?i#J$1DAn$>K<>3eVON;I2P#0zKS&!eN*D zVzn8{>~cfas{C#7YJ1meDABpdKKqbcLaZ}bf~o!Qin+v0leeyy zDOA%-y{+%>3!fu6{qUPlOQG%P^%-6t@|y%T!YOPg47H0|+}KQWW;t}(Yjv0jWGoq~ zuN%*-)H5&EOWJ9CI(w!Ee|hFhBV&MUoo3V=J*UBtDY%(f%S7|USMx1T4^d%mvuGtQkq_Qdd*%{iIB-Lj=12x5gs6zaipBQ% zc;BuftpAbZJg;qOcOlUNTGFZo?vR;Po8bL&?j}4M|)(2Z8Tz` zEA{RphHiQ1txE!_zw=xA)vmgKFVGN?8#VJw^UpSFFXR4oh{U=e^}3r%`$|Z>wmKC> zpVC3X$#ty{ZVCgzXLK)^`WurvPAgDFUVnVH=+QHr*8U{7Q%Y|M~M> zh?qQnw)`vein}5~bAx)?lh#IkSNDvm%)q>97>4@`1YXpPQ%5|JDt)y-jWy| ztKv@-yapWQcUp%siatI5>?aJRB03mPNqiS5+sH>n8gnGAq>?|Sab43`m|Q+IFZ6DLM^kT(+=FhB^@#y804V6b;6?)dQ=(qb^Y9VX zSz7=HMCp<1D2~h30rZ)3dRH0z#G()yklr-1()5C=_%40w_K|{G&N{vW|a)_o&Etx_AS?SRph}7AlHvwk5rWrfmyA zVYZJFw3}-jL&S0Ku122H>A@p5iLq^w5g~zQ+Wc_%cs7UsT90^P@^i;<9o~=NkM1W2tGYK2pA32|STv0gl`DM11Mt_!K{4{_YO{2e% zcA8)}j>X1bv+X2oJAlemDBJW!{HU|a={?IPhDUH_22kM&fr_qzq2h&cr^M)}BZ)}~ zUfudaoIhu$^J&WC=lVCd)~AaQL@4TB;+8fEg29|Q#C2^53Yl%$(z0J@!3CbpiRBRo zE?_%BLpf7Qh|+)DHYkaCx4#o`)sE525DqKmz=L4xlW&AR)bt7+uY|ON zCG{F(wjBSjL&PDug228;U9;8pN;hau`Pe)AI}uOYr@xjUTRKTRM0S&d1smq+rrVl1 zSa$1_)pTo80ElH0M5>}br7Qt&S2t+SZYTnCYiU=%N#syPX`By;4XNP?s*3^$gn~R1 zd89d}t#4#BQ5MAkQ7)K6yS|qeFjhxSbR0zkPCk#;`OvtyWuja}#eaAp{=4R06M%vx zBE&|sgP`{JF@v=TLCsKvPEA|YqFcWpCOR~4`z4Se-C?>nbJYdRKmjngue(9tb1J!2 zHLZFQ^_iyh)+cHoq+&_21(fF&V)IBzWu>J4yEuD9I(7;v!ya-Rod1l>1i|p-1&Tp6 z+5gb%kJODtR{aGVXlIfW%;wC4I>@je>5~3pDF`g@ru~SxWeRJk-;@8U*gXM%v8dxn zKVkOC{s-1g%pZmQAK`Uk*-+e9UZaFiPt)s5Hwbb2MW5*aqe?gO{#+&?^*;#eQg<16 z%?iN?eBl5x+H|1zN!KfL$FhL>vwyfU;dECLPXrp@`P|lQ`HUM*E<=hsAGC2Tx}ln9 zH(yRy%g`l^s-1OQ)`i2_0|YzdotD&yP!T%o%=3Uxq6mo8>MuZF%X$N%w%w)$$`&o- zC_7h2M6cii(9p#co4}kkx6TZZET1PTjUa2X(Dml(%YI$AMHR$ujFje@`Fjo5+3m*O zsOrlqIaVh*jsW zLvasdDU5Cq^Im)Zk=3{5{WD2CFHL-P)@=Q8&tkU*{`p*^H~vvVQ3ad5qJj>h!>&^_ zR0{6G-M8DJ`icdbkU}>$Tp?X+S+{bIhli1swdUmV(oMh^ui|83k)d^4xMrF39x=`5 zOL=*AxjNOXD+(fnmkPy5sRvpdpt*hDuMf+VG- zYhRp^ySlPgRvH9MR}YH8N{e9Vph`@5w(_`0fF*F9Tie*U(R%#!I(Td1duH@ZR&?^~ zVMy9H;bkMDhM10Y^-PHc%r;!SUx3)VG}s76@j!YbD^2`v4*$KMp2LoVcYaw8{r0?=%<>Nz;?*5blQmLkP_WQC@^?kpf`;qMn*?Rc^qec-Z3t`fYHvU2Vetk>dp)l zJsx+OkOcPRcZ9@E_P$)rTATIy)PJbJ|4(vkud3tvy`{4grj&brMae7hkO^u`wqBVr zU}0h5R#ae<^?+MkOOhhp4VKk1VTDb(QJ90gBmad9?cEY=ie{fpmzO*WEOpYG$66!# zEH5O%*lU%WEkJkbaHd&5Q+?j>7N5&Z>P{L(8fk&c!iWK@f!U%7Ak2Sirh1WH3UqNd z>?gh(*pKJ)QuKf^5U}ch2x-(S&rS*$R@76e+aG+lc+2BJ_VHuK5@KV;Am7V;r#bVc zw6BlPjIf#|&LkjIM9TI7U3N$#tHe@a@!D9*8|(b^>d&8LQdHAyRX${8NwL{5Gc(KG zzWwHh+Gh1sPm$4hd)g2cQAiP+m6~XPIUccCY~el}^DzA5CExlE=aT&4k>9gA*k>lf zI75@vjnScde}xp^*K?`2#KoxfjXaKBs z_9S= ztt?;*dB45O!CekyxKy{eb=bsga0-#yt*N*rzQ&oHo3nNTAkL}lgs#1Q=GpS1N$^thJNI)PE7$V zHWQ3y_Lmza1#fTw#Om?n`S-%varbjoTXLOQSXp0yN35IOlJ)pe3Z}Wana64F)@Xa0 zR>&oPa!e?+sJx`lI}qr`k)oD?v>heH)vf~6?koGrPTsGn$@ys?LA86!X=+Af)Rs&w z8;cb=-z#>0KtyCRzS*9kXZa*3D5yT4Eicn$+2Ti`U5YK(2W7?#*C%#Jz%St7c5*T> zIh(oM;D7c%Xv7^oDE1RCJn!f$UJiymda)PpzDR6|^`I;gR#g6@waw9$G?{bfn=D|V z7-&%UTBL@gD@F^mpo0k1w6ZcXz5?#C>k(LPA<`adE=+ zrYqYEqpdv73nqxXU3gssG02ad0Bk!y?*?W?A2pDuOZES%`fk+YxbHl;$y19eeC9jRu0JUl#C>Bc*Q-oNM4D6&sG zZw5%sbfTP8?j1%AuLSaxhtnscUz0VdW@u#H_C4?u1kDKW>u&pKX1YQQG42AeSBJo6 ze!F1%44EAjJbaTP{_v5sInDQ8|ND-_6L4AfC2ySHyJ`41=5!cwE?6O*uJ;BHCc5$( z@lqfS$Km_r$$4+E+^39;jF_}_ZVVa|F`Mnv2t!@1sWBH_RLR)Y^_NN@GyftY;!gYc z+UYjjPC=CK{0hJ=U`<)(fHUmnYjn-|U{p(nfUixYtjUlJmBL!-7+zgyU#|btC~?jaNL7hN zHljW2!w1O+UR3Grfp%`8FJ2sbDdJXGa0_TF=HNcuF>DPtvH%F~9y|tW(yTpoR^YMI z{E!TY(qXFeSE>T&rcFPM+SUMOLETcN@9{x!qZd!6l+N8&cy`i;|5mvt&K#t(RRoGX zw%s-IETVqo8Ga@(1)CKz5W?3GBWlSSXcm)|m34-dRTk6}W0GRb1-Dj_56GWbB&Cm? zJa#iKuhjC$@Lul$f0w_Z9|cOX{fD*jo@I*VMACLvgR)7)ZY-ExxA=SZtCufXzJC2G z;{2<##H@q!N2y!UkEU@!+Y$YCK8x57KpH=!L<(*Y9!WUnEVs zA8z?(TlSS&lUrzX*eJk}1+Su|$iea@z$HpbN`{x`y8r(<(RQYukVIZaVJJ~4K=cqx zk}2k9$?AW3QdPDu-mZ^$X%j#vYEjW#$PL)*GIDZ7gS32>z2`~aG)4&-S9}Agp@iXA z5J!?l*T$@ix9cbdpcs#;p6f-?zf zsOFtY%GF3s9j%nR9oZ8-MQTtf!w4dNn_VmS?sIVF6j5Pi1m^$+xQIV*AlLD+uWn2R z{=vOUV)rKE=flq8Fei!cekc~}w-0BM_2hQnd%;))P+mJ!A1VL9%E~GZXB24QWcPkO+;A!5M``Fjt-@m>T$a@rkK45NJK{eG4keKFxjpL;oRZF|4wS>g|ADry$Cy40j zL|nfsceIP;9H{8=f1KBms&RUCbrp$yymUZlTbuHY*Xw|P*nf}zH{?@aK&_J8RPnsR z*P0q@y*nZRfXCvj3(n3UV8?NVlz*zIkX$b{ZlwKDV3TwxXgpU1$DAhqagW_-bG$d@ z1HrNWBOfB4dU%-p)S<~P%yVh>biIE4g-ehkOf^;)9e!;%{Np*lZta=-p2N>h3Wxu? zuEkz;)y4`s`rz|#IOgW6Y*#IN3RS?S{~DFDwatF}Mn_rs_m8A+IS}S!Mu=j@dV?WE z)EB-$zn*ZBX6{{6+%F#6n|VKyUXKEXymOlMq^%$_3BUuX*0@NO4@ztHZneW0V}?RB zI~8L_@d&SgfIz>+FjU5no3A&DZl6zjO2I7w&}8JzWgA+gP3?i;KGY6^ZU`x2qNJp3 zftqF3^=@h^SyAxFe?0N^eQs16`f^{ zLoLfT+i#d_DYg-`fNJ1@gdbH#$GaBIM?x4(qjIf1Ukf1TBgHHXv z^Nru~Xlv3%mAAYJX}=~ARm;P&G;oBB&l8uLcU`z~NIS)Cd=6@?NQm$eela99bUEJDh*RI9kjL*!>baKw0 z?2zpRHOBKTOGrhzzCG4XhkSAyd?t%@-=|O0)XK&?FY7e0v9X;Kcc3ZD`26c$cuk+P z>&N^1tA2D8Oh|(m-Z_qxGmJc!@6o{jzE5}xo=)rK8m-6nTnvArec}u8bMrc4vOaR4 zh=ce`LqjM4e*RD+1!j@@tJyAM}h27YVY^jvdSaIbTf-`>gpyH>;#$lF*y9_O)p z82S$2g^5IS!3uFP6nBl<%34^Y-|a2_@x&0wNZ@wRNK8wjBfZZ{pBN_MOmKDKz^AS& zbpN|Dx_5}nvN7`C&!V5sr=uO%qH1~;5D@m{$zeL<_d?2e5Oro^Q%wy7UsKk}sbF*o z`bdlb+we6H-Wp6xoE;A6;=S+@qW-Yp^u6BSt{I#cfD2G$_i5wuT@UGrZ{dp5HT7nj z1|c1bEG8&EoL{Z)byQVD57P)LLyHG>;04o4L9dpU>n|^uN0`P!=yeY2v1dU!XIz7|&gO@sakDrm5S^C(q zV^@=Nfe|KDB#@At^9#V?q5C7G+c|xGeM57r>(j{do#x-XjqdqiBxm~VUC1I)3oeX+ z1&yE@jlg-5lKp=jK_DTF;P+9VsohKEIf+J)rYOc{0>@m86MG}b+Bq^xLFk5g55eMc=*=KElDq7KD5@5B4|X3Q4UB89X3{r3mgjTZR}ME5KraSg7#L9a+~%uzRVV*i=uI)pBAx6j>vh#fH*x{m$obc)L> zF4k^{5@P=R`7>FmOg9z!7v*=n!ow+iLArf>@KYjrmWP+6#llS)ui)WsZW6pOXeIjh zweS;t^8N{7OW?@1J+kY2c*HAeo}L#nV9(J85upQDku@%9dF|SBh^JP~Kd!8*l8wAz z4#6hbY->hB^m}461S8wF_ZG)g3akhHMq-Ai65-kz=Mk+{Fth$iR%eRlFz(aUO@ha> ztq1px;RN1_b1yq<)c z&Ud8Fn7eyCESD1_=Q#d;ZQV$tx`2D<6@Ol@e*>qezN>42o11<2^xtQK>{E+sKYom4 zO}_-4gv=-==i1uZK`>jl^&e)XZ69eyTS08%Rm0GdkidunJaXhKo4?2}TO8}hRdp+q zc=c#%ufzTHlzx)a`emGiYrDTD7V8DmqsIR-h#i%@7E;)&U8Zr%0Q4Bt-){)kgfuO^ z28BH6^+mma@7G7Q=o#32K;c|9^4!>(Aw12O>E%h&(-Q4g zJ^OIok^CH#w7_2Enr!!@b5o)NQ>>|}1VbgBn2>M*->%&COa-H1!VSQZtmw87iD2R4z9QZIY*2YQ}-e@*W z+1LY{2OnN^A|oTaezC~Z?I|S(=(TG&4k3MTlH|0twI7^V*=(j4;mm#QDO#p?;kUt+ zz2YH;H^E~`N6b#O_cqN=yh68c-@ff_-qyy5zj=-(dJg3$v_^@}v}$%~wsz7Bwtqh+ zXh_KLFr3&|hAUL^t}ms=%fru!d3+?fZpyKfT)r?)tYwTJbj!!*;e?OTgyGkirk>Y{ zriI(?!}1}89g`^*%Ua)5rq`Wfswdw$2uusa*z^`g&%2IyU(3?#eerZ34lW)(aX6dT z_VV_YUMYfyk4za)v2I2X#Di~A0VUh5Cjs(Jd>4Vr+!Xk|r7?N|4?_avxm=&hLAZcr~u2cf6B6!YAm(Ja@izRwkBpe(8+W*~dHo zzw;M5

LOd+coZ7~%K42oB+!kVk2R`1S$<`9)N5E)Nv3fQSA@;U}x9(DfFW+`WthUQhI=*&<3{V{mC7$4p{9?L!=w&j0@fSxkr;bjZGes>j3 zKlv#{s++&5yc|KDJCW4c(4^3D`>@$rnBo|_Qv0yG#$a0kCcDHLH`;$}@hut2zprZ2 z!&P~iH;u8&IkW4d+YKYsF$~vG3)H?ArA)vDouCIFl`BNhQ&H?M@IkaXOc<9xu5sY3J&f z^Kze;AYt%gfu5>>-4vmDMzrT}oU_|Isa>nT5GJNFG`TLPV}9u09igA`^YmO|Bh$rx z$%}*#7XKD31}P)e?CGDlutEztVj3~)Mj@>o;jD`Kfu6&L#6EeuUQ0ak0ll}VZpeQ3 z)3fqoVnyd=_oMfU(d@^|_Sem*k<6gKMiXOb&LkGw@MjI8)+M@9n12=|>&Dz6!3yNg zLTsK<3UONBx~`^$cIofMDLzFXyXp5x4f{yH5*B*Dh6~UDmr`N^NdzGYNo#Q%Ec$(R+C|4(`M;;7kYBlYWn%Q+ zwrjA?Ba82@E)X3124E4l|F78oU$Om<*tU+A=J)%twd8c@Mnbv1yVj4_sC7DcAXGXa^j|R$Af0H=$Wl5$lOd?jpXzO!7(UrkTZo+ z^7-@X+Y3peiD!-bD}7CYhjd;!)E_jB61mq0k>y&}q}C~*O*awTS{Z1KFiU?q1*IMe zeG03*$1dBaqKj z=+L&2N4%*mklXjphEBdD;PYTc#$yr)p9O@MHRG3|v`jYXm9=ak@OZaE0DOKFWrjO} zIHlECbp1y*Fsc-*k~}+3FBaSWM?obCT@ov5t*EgiMdQqA(1pMJ=P<^~Vi)Urj0xec z#acWDi>2mahE+Vl$N+e%8pY*liN|F%2(o493qquoLHf6$KS!tnq(8GEsZ8V~Y~Ks9 z8B=Jrl!uZU+xb`OP#iJwW7Q2W2Xe^Wke;UI4R8@hpZ;rq&004m<&{?s+jf+v{puUp zS6OH$Z7jS_?^;CS5lgRkbzRF2nB zXOHbMH5kkzSg5sW)-=x8ZJm_Ppc$yWRm^_$uVVFb1{a|tr7Q=lY-M3OoMND@yGH4o z0kS<2?fcxY;4aDC~fmu}! ziWcOkgzP5*2d3rp)~>GsSuzVYra3_kmw-!;tm|+b7NiGvvk|d{O5o6Ww=e6 zjRO3R0)#LX5VwdXRG=I@xs3I$uCrp7cPK}(AH#*9gGYhh!(hwoFaX3|wR9WTY9%k7 zd9=|%)p^LITF-E$!J#zB0vJVYp+N7=*_#l0Riw5ow(10-Yz^nW8S$+c&diOCLGP6h z%}_Y;3d$mygfFaohHA7R0Q-8L4UJX5F=umVw|kdM!_ooYVFAkBST6!RyeZVY$y&P4 zN483f%spRt=1?5J*d|+A3a(bGP~U1pcP_BZu+qRwPTw)!7<`h?nY$82=kYq8JXhC= z)A^$W&A%Q1F+Gx1JT^YJyM@Tc0fEai~`m~X?klG5kMg&s$C@1cl;TDq0ryYFVzx1?%h zwKPl9MM1wvMrgb)a?-@`cigP`7B=Xj7dvtj7LTI%bC?|zC%!tF55e_+^&3u73Fslz zog$;RIi}V+@gwWtNwebB^|I~tjUr>;GofFKP7#;Zu%`T;kKb@x?#Z(n^Yj?N2&Dqo zij&^Plwa8tao2pKXv`7*pPse=YdpOCz@t*n&qvA0)rv(|&CZO-M4EbF8>f@VH1BcN zfF{nQ()-;`BMcWj2wlrP?xh~MW9vD?ZINjGoF$M0@faM4C5duQN#HgLNP<&;;ozj9 zR7*R@eLHA1y?x}JRDQah-DLZGza3sSoyW%P0_-wh6c8UgIO+m&?bZ3mm9gn!fb_It zq(z}AQpR(7#=zfman5)fl*rn~`fsR^tI;F&`<9Jbw;2BFoGltW98zMrc;(~R*<}W^XZ5X zJF2o9&8()CBjm_d5;?ivufD3{lG38?-=^{;}tAKBofYN=b6EVe*_YYgnb zav~vTKK)ZF-aBHH$gXW|WZy5QmlsL4=F!L@~`zNNL-B6OV!P?w@2`J7Q=6^7g4=Ogz`LS5}kHL{C9p>P8)^`K?u{Shc;j(A`XEGb`qe)_AI&bCQ>6b`K-Tss>-=HnbJ zVL+CD$anw{U_=$EdbT#X^FL(rECQWEl*sB=#fDi7Q{`AENyW21fd_weKB%Q0b9pH#26&F4@(ji{|#aS7Q2)#Pc4smAVg z2wsMX3;t0(HaE9`ZYK$rPe9KZ$`6ajFqrJn0^qk8#NgG-i@A)oy)}KC7+UjL2N2J} z^x5AbgKA=zBruPBeL`bRg)~69GYV(I)z765a52)nTR_1@LBgv6xj+eom|`wONAlOR zj>Y3GK`rIU zrf6O>RZXK16|4_s3zjYcj1`|A_y)^K-&D0YK8HQ+&k#+8TSf*epKABBnWd+Ez5GAF zpYmsa@nHBMo$EcnKnI$|2A=P!ST~Rs<8H?i7y+;JDy_@JbBn^!H`!2;kp%1}r3D_z zXL-k_<)8$M2 zLV~y4MaV;Fh^gSL|FbY&B*=iffG|e2 z>p1ij9~*;mji^(vzI``bY{l9M5OMGEQ(SyW9Jp4nfh$J-(Q^MH*GOGR;F<0b6Qry znFO1~Rx&DYSyL9%kC6bQ!+;8FM}eT;Zfz;AEDBthn2%Bovzy3MFJ14MezOv_3|0NZ zD*30&bvn{`6M8VeCPq?LSGC*h09$|eoHh5OU|uKFo*P1wA`*}`tua}&Xcw8`1lh_! zNJxm15e#uy3(!`s9|oYc6r!RE(^uKxD1MV@+J0(Sf;=NxZewO@B8kHcLO;()bpPX2xCPgUyH zKN^6fZ2pXY_K)`qKa6CfIGoUA!j9Sfqf=~=pxpRSgCdkrC=7Sz9&NboDIE0eU2Sl9 z14ok!@ov_a|4=$wgFMZ4V0u59+l4MnfCSnmJc%xFKqRK&C)SH|@MPdAWxh81uV=y% z8r`OBR-2%9GWt{Jr6^-M*s8w+rgi3ek|xW{qN_4TE+KR+ll0`CvzRTOPof*2L=ynD zP;i>+WYbnlSZVMx{(hhAI-c6!T#I1un)1(YQ~#P?E*`$PN}G980cY}D1OI8au^TZp zDOT0f#g~o=5Du$V#<@n}b0xD+El=KSbhN2qNlHLS+Zk0f4AU#) zB)MB8;eCx#+gIK~KJwq?5=6oDHb9iaGU^+`Xr^ec#hh~yr1aoh+5 z8L(azvhU~)pNMbPh0g5HZ#(gYh7_~!z0v5-X$}rCi|SXX6aUuAU41er7s3MB(Efw9 zU2X%^eOLOnmhxIzQ&L})ojuPVyIHHZ#iK{(fb}tt01a0*FvKMQ>Kga_D17&f_d(bH?z5`(}+-LVXdP~Bn){FiO?;=U$R5V~MR5%?jm(VaC z?L=+QVK$G6kF4|%dl)d}?kCsg;s9nXQ}B^iH_Nuh%ih3=M_6`aRtjq z<3ZF9Z~G$M?{G5}@XRhQCx8OrneMt3BtJ*~R8`yRv$&c|*Env;jP^p|^R?YKwb&r6 zE1mHC!)|x7Nd{I;VT=`fRb#~fTM9fCIE=*-T?ht2TPzZG&<=zR>1-{7sk`L2&++c|lI3=&8V$|8*L-M~ zn*KOe5u}l|5{aM>^C$J2CKk=dV4Q!eqQWnT1qUMS1;TI_7N0-thbZLC5V+w?w zSDB-1uRDLD?hOPW%D2TH`JPJvozw~)X@QMGzXLC|fUnZQZk9|AZG2{aGmfeKJ?gJr zPz1&-HS_Wj7dpGPYpcs$N*$dYUAQH4+6%caI`^!S4R)1Y1-{s`N*b_A4Qs4XNF-S~ z(JI|Tt3=8e0f3)^OW$wWP)q`Og)G#CGz6k6;t@?t=v)~^S5I9Wmwf3FK&qER*e-sg zIa+z3)I>nL#mFJFt8ojg!O;)=BTdQ9Hk%i=PF+gXrqSEy7m_3m*RQw_v>-qmQgO%` z+WzeQTzey)Zu9JRj!!;Q>G>0S^mmN?`yR~-ac>=y)IOI4VUio6HqMt~JEHx2m97!) zQcU=^is)L=bKHh`_tRiDm{fXF3)bA}u2gF@;ijSJ><1_&-UFMX9N1EC(~!?-+rIivgeLj78sSPsR?XWy;lb{aj2OU% z(@vdK!G?l+L2YxcC1aCeCEImx89)kZ{s?l-U9G$tBn6$&Jv6Up9WLVLTsr9u7T6ZL z)f`d?rds21?c6z?v*nci|J7(-5!j5*?VdLUyS}S@1&pag)LRzxtjP_=P*IHiYLCa` z?&t8Y;ZB&^xcQ;xWek~(%QON$GzA{GuVEPQB26K;GR&O7BQkDhrsq3IsR=BLh2H$FUu#-jKqS}pp6cT5oC z##ns`MAED%F!Ho#>rCL-hW3d2ZjoBJk5<;@#fc@NP0`AQr&kg8*z9LBpF}bLOv!ek~#81u3(dl zcWyQbp~x=ju^qRHRWgMIFE!Tu@Gc1u(-%QmFn5u2g}cMpcte_EVlL^U+E=ima{X8n z=Vft}3!D)C2H#E&`y<^Lx3siE$cBzxOoigZf8M)Lh@E|p#^%4z;6lp`^A-5|9UG~| z>m-JS4usn~+m*JeSO)^6To`vkHOfA!H}KWPyD0vZRFHI6GIXtTy>08VYf13ya$xq_ ztp$Nt@lqEr;y!@hsoybjZ5s|vEbX7YyV#cVffKU9g$vpCyW(|CDOi=KqPMs^KvixA zLGZHBzya)>^eJ%IOvw3n61TVC3qfwui-2G!P)W+zojumZH0Bv56fy;6)wBtY2Y2b@((Wv!4(Vf}D8x$0?M@Wc?EYQw~%Qy2B3XV5?y> z!ClAVA_F=W(dEjAc6|%K?h#tq*n)@H*PaL6L+Fdmgz{d_^#B8*bo5W|iFQm=gB+(( zO2=7KXqVv_QNboi-eoxNwlP0*;6-|JU#zg7;(7ux9IqSyXFbC0@Ms4g^x-ufdXeb? z8&UL!hwgufB^5xUl=pvDDbDd>rEPj~v1evB%-aMJcH;q4~C51{E_h z2D5<6TgfPpFUkO3<{c_gcUSYO%*RMxp5a1^i#)o&QSn)5Yl6Qx>{~t^;M8wpwSPZU zU9f(Mm)X7eBYsHKi|!9H?Rn}6^E#+RDuYB~kpyYbLOAEmF#$kJuL*ajR#~<*NKJUB@vb1q*g?WKom`#h$v8WrCOzfg!HVn9B^g>vtHrAOc|vDD1;zWpJyMg<$;` z;hf%`$$rMGaW7@9iWk^3tqAO74-8%2{q(E`tm-YL&uBBmN|24(N^g;zesEMI96CG< zNhh5z)@aIkiq+#$rL1!Tw4iB-iYiOuqPs_MMRFhkzHR^NyM6vldvhKTVsw>?r%?!{W))krSJx2Nnx7@Y0K)3LQk zzGHili?FR`9*0eNX0F}5E72)Mw+@@_#fqQ(SXvEIaT^`SYVL;h(HY%gP3glE+;m-x z^j_Pgc*OMG36;%z-Q8UZMUiO!J^Rb7pdzkw4`ahLUSu#~+;~5boIE5s7C)gOBq~(T zef2yvG==sqWA}PZN*~H{N1*{vktFt+Im!@2wbA&M#m%h|{1gcn_1MTpwWH^fcc+~3 zoE2jI=9eydr%L?$ZG2)1I3O+*C%v)5!D>Nr36-c3bDcxHnpEPGK+$~)T60y^*K=r( zRKr?u#q2+IUJy`_7sARm5-IDRvDz69PJEPKT)+9=XIbTVcub?(H})LwzjqKFhp1!8 zW5sSs#ld@uF+RYBu$D{(n*wh`*XofeR>cJb0q*qe8-(23?%XwFhlP5_^uF!7++f+` z_mKQ?NHlf#uzmDH-dQrXt5GfBycX|23kg3owc@Ho=S`bBhU`jodzPbs4$*$>nsXh6 zt=z9mvvW+K2Rsy@gI=DM3b5xduB*IqnP zDlgu||M+UxOZIuafVapUP&tXd*CvNn$?|x~BGob+umABiB^=N~o3}1KxocUHOF=g+ zuB#JbW%&VGfOOy9BS(0oc7+E2aS@SEL_!drN5>G}x=Xp!D}8{se2w+P`iLlJOuh+~ znYshIX1jmu-`B+E?T2i+{dV&1(x7js@WGwV4EdD!wn{Lca^B{ykK%7ku)Fi`zy5o6 zToO3{4}0$&k7fJ+0pFx(a!DwgN|KfAo!LN=QD!vA&bn+$Br73gRz}&fx6EWl_R3z# z-s|}s`rh}=_j~`IznLFp@|GD|yc=wA zV&1{_M-w=U657yr+u#g3~`rcnOnY(sH)EcZq%d{@b4ovPCf`ttdIRMH6U%9& z$b^dG!!bCle!P&1^4^QH|GP_eK4BnXHxaqa9=Cf_N8N*~yb?RH1NcHf64tdY36sLg z!q(lE`OnP;KV)(^ID2|(OF>}QevC(jf=%Jp%jmPQD0m(hgLm0apI-m=_ap3iC~a3* zT4{n2i(MBX*g>vb{4jvN38W=(C{CecNo_f8JH4&H-^-s*H)aGozpzK-(Jru>=)Xqg zU!$^nQ|;Kge~rrjED2bve~rrjIzpm5qf|7%qKH7frfM=GdU zr6-N=?)87fwNZq4t?K4=!XJji654~Oe=S?p=05Y;ZN=cE;${35v)Zbod?*TvJKUY$ z2Fv6Y_XJ^o1$9wnxSQ05#erqnG{RDGF6<~DbZ@D9-;zQJpABzp~gvLnz!p_qtWw|PqmmLy&%K?8l(cml5Y zq(j0)#Vs^+_cHFfoJ$s7ZC7^1(COU|YjGW}qMLCDMcM$9g4C$c@Ll$?_Zk%coRCCm z!9|v@$$w01u1S8>@Q4h3W+4ez)aL%y71%$rr*5{}46{JMYsA5~2O>xXRFYrh zNl(xZM;${^GaE$BWqNH=yKngKhZ`er%KL>j0#7YwQR z{hZu`yY6?_DiY~kgSV`9U2b=YSoGhm^6ysJwO#*ni2mIw|74r~wJLv`q`&sezgy+s ztpY3XuLJsRI{%GT{*6`sH~#wnDy*e+D2xA73*g_l)9Bi@Aim6v#~O36gE!sPib2`D>Nf1qhsO$oU@Ty)L$oBB z#-(s*^y&i<}c9zCsD&jVk7?P_Rflc^;0Dy`Y6dW-0!%puG%*Fpa+>7?Vt`fqv7pp0IvN_{ z(cavh=jz^YF}IBYL+2XJN(sJgv{n2LHez@33P&6A+ zsEZ?z5gu#vmDV8+S|8U>V3o>-niSb2F9Xab08s>wbhyFXLT(N7Ixd?tQ%cIW?|(7> zNvVnO6tajxBdnj@V|5LvQ5!R4ygO`%y=xfdzCWJZq_6CI{2u-Y9h4H>@1_0b%4Q&b z1h10OI~CFV!rAG>`okF%jeskRcf$X>ce%&ROq{-vX|vA17@oDeeuQvgj~3o5qpeqB zkGhmU61cw!G&wIJ#w;*B+b)3^H4cN>pS!5n`p;eDI}Hr;ahUM-1u)5*({TX#;qpDY zsDp5!fb72p^egg-8Nn$#fM+TuUMg(Y@$}9K%Q5~Mz{I5d!PrPEfB%jg4MMyE0$)2n zXlQ;UroOD_+}a!{0LopvkS1|Q@9i@;fkiG~*>HX?ZyJ#;t_F%^k?4m$mb|x(m8U1j})@rL1r_D+Cg5~b-t6rS-G9U$Tn{^ss z-`9XVvzYMJCv_PNRKO%+F%A`Z`M(nZSor#apRfJtXLUcO8l1MwjSYVKW<`Pp8wX{D z+j&2p9BzWq+B*<3$^}itVJ+V5DjqgJ5X2F;j3M0u213Ln(j6UcF2xQ9su*h$55B|1 zZ?{(ozh37!<~9ZAphwUIwvimd89CClx!Sx>p56b1*BZzfS0h(zAKvszX-C9!3!wYQ ztmud>Oe3L*s(CqFI#MgB#AIyKW>wJku zG0{f#M9=(2W_qbdVcvMtJ`B$WW0G~e(Pw4?I61ucvZZAfzA~p=M|O3@cK;N?wv--s zX@+^{7U(w#O~Dp3=NGKn1YIV}weC^jAdu`69^yNEAyss3h*2bDUm`F(PMONNT8b<^ zZd|GY8q>a|?4l0j1%S}fn8#e~V<68z9!+WG%|3NQt$l|h0W>!XQ>^i%J#gI8bYHtBdYnaZL%L-;LOw|P@F__we*BcQpUa4SvoKs+?X|MkS zhDFwzFz^-vss9*XGIuX_kn)zVRr#iSCwHIy{6ggRYNUSuGcw1Pe#H9(RGp?x#gqz_ zy^S=mG7xu(r)bt&oJtNRHz*@^fV&{607KN4w~4*(mzSFq;0`DoeFD3kfH`{PcI6IR zhTu~bsTRFnw*f+N!*20)D>!RaIkA-XweUYeTD#w^sK}0gi2T{IhhGHPS|iGxP2ggK zu*Ea++~3xLv%l@Y7e@KE9@MVyI|GknBrqLOpbH+)08iIXr=>?VGY9j;C-6CFg7;7w zfj+N%UcVc~+&Y1i6hTHBsDqgEjoHD7+Yt>4!&EU=r`6#gc}!8^$Qy$uFt(xl5-`!; zEzi1o=xop*`E774VfNH@t|r`ci`R1z0@2)I)|eLcTg&>HwrZC@wmh>x}%UeFHN z^5y~%xL&4sYHUpg+{UE zndQNrnX-Wa4?pllzHCw^I8{xyBfjNG5S~urFF5cv#WZ_8^G@|(O)}~c6#55}cXvOC z^q^P4b9&=9Hf{t-F^DE~N=%#LOhNoK^kWRTZT=KApX+#wEj|Bul;hpRdv2$%5aA+Mh54`egZ6Dr@BIpnUU)& z27Bteorqw^qUsZ~Tv%mEJL~0Fk$R|0{ zh|oLJh^-NjS7iYOZumshd}xqU2D~#Z*GL$nG=Ot<*3b|R);NTn|U*bmN0LE1>4;i2%$ zWNTs%&=JQ-_jmEA7WL{}R3I3D^N==S>1w6xDT+pmg{a7~p4MDlea2=_mqO6f-V9HO zbc#X^KV8wZ;Vmsqo13|OnC1Jq*wty3;ZAvLM?U&LcjgrZ!=(-5H zvhsoQXEhES_4+tzQ7hOW4lOYlYP3&-m#bDWwMK?&hG~+V1^d1ZQWzphLi2XLDoNCX$6LNMAWAsvqjA>A%eWC+#5{UWfn#85gn8{>-H z>GUchi!ODWH;gdhcFG=N+q3q+SNI;2l`As64`e_9*;*1xVJ! z{C-b^{Rk%$u)iOH-Eicgecoj(ns0fcPt`jw?a|B+yA7cA8XUOAAlj{JV>@H>v@a4w zM8=;p_0g8D`iNF|2%6)z^4$YOM~VC_PyMi+F9Cn<;Pn4&gO1Y}jkhjA`O1i!Iw?+2$6 zvIuCT3HY)Ij#nKTOv^lwL8f8x%>wq~(c4m!6AfvX&3QBOGxLJdo-BnuSp+|z`397k zUIccQ>G(;Kp1e^(Ad>=Oj=5U8EeptE)D0%#tijb;9e(Vi(W5qSFawPRZk2n!f$a=l zR9z4dz22d-t%0t=Ng~n)f$gQi{Ju?N{<$v<^ZCV2eCpegY$=Vs?H~?Hy!8*b(HjJi z9cdQtiD(d{c|ED>dk{)5cIfM4J`m3wBWnaAm`M0p`G_zI;W(wB!5@ekepdEP03xzC z81Y0oOni(RQF=Wu353j+4EIi*mcetJSp4;?MR}7!LAY+=fUBxxewt)EPialsCd8Zd%nlF|6`Ju%%GkpTlf$%w zq(fi$*01TUWShiU^h(+qn4)^}nwCR*7h)fn7ML}(I?3}52aLowCNT?UAIRuispR1n z?@nr~oSe2F6|f1M$2v5M;m7Pd#!IW2l^ICY=u={kH;QipX4dsP#o(hEJ`PsI#{&Xy zA#hzUsbo2{HEBUfJQN zqO$q;Qu9**C`i-1&*zg((dcvHiEhjfKf|)5M8R8pNU}q-kY8ERr)25}%adV@gi~97 zZ;K!avrN_1CWam)y+B!Ntd52po=3tNOv>am1(Lj2PnN7N3AYH3c{Ip|zuy2ZvRYR< zsu`dR<7q;(J&IOFwJm?@X|xn@MG5h;cNeS-lPMAEx%c&0_w{rRwb@hM-9|H6WkW8W zF-rY>V08m#C&eN6W?sOp+~L!brR%Bfn8>jNjnGtTC;dTo9Nc+yRX z->joF@wrQ8g0ih1HfCo;cEK>qIKbU{`(L6oam{ivE~KJANC%fwXb zuHucF;%FeJCh@Y5J)F#W&UT_az9)^XbS1561BAopf@pLE2{S7W{e=3{HQ@{(f^$Wd zwbMlj1qAPA&HX2VvE0dh!`E+i?SfZ~$wN_K>nBg<4hVx9ffo4RJvv?p-UTGszQYtq z#$h+7t@%iKn$0n3cS>(m{<596>+2FkP903UtTd&WM3FHJ%97Vw{i^cjzQtMvq>}SU zPAMAdCLDc_ATiv@-5htw)!^^Ai#1_breb1|Mk_bs3W3*)+0jJTlE0$&L$7uQJ_lsy~s`r?`dK-m%7+^>`~PPv!<@?vR{+y1-+p?47uW2 zMkhKjrf)IXdU#T2|F~*DzcT5sR#N8MCRrU1^w$=~S6`=vBx4H z>$KXAGGLVANE?vCt2eh^XBV6)HrZH#Qc4hg0hLQQQ!p z8ms-H(R$Jf3`89AU3H^YADpf1>7vr;x4=F=CNB!r^3h95Y1@5V{*#uED50}7KhbZy zJ3h2f1LxQ^@N0*$5QyrSdFj7T)BB3FM@#+gG!YaubR*ftn^R26Ga4`z()qj~)RWo0zswYsW z;zQ*pO$WXwzQpcDJ3dk zOj3ljNQ)kJJAo0c?H@|@jdC!Y=ZvCS_T`|_B6(h<4iXbPs#sJEUNpMfYJF?U$EK@t zF-1k7**9?CTmUpvnn6qEb)PgZf8_>f@r9^7_Pt^4I!ZBkUOCP;E8BRs!es?l%n%dr z!zNQs?%6gQDamn* zw=x{mlMcbW?gb}}oeN-NK|VtyD|d$#x>(TmX*7x(_|Vd;Ho57>Q$VKy zVWd7772}?8E#y}l8tM{`W&B(L(;AEh-o6&9s3CBZZr`e;FtKk*Ysb({s@@h*mhd%# zQ}fgJlhayrWM$0=H|VKs#5^B4_D?z0f(wc$*PYc*?DF)q?4rQI{KNgX&(gjJ4(XW+ z7{9KAdJUl0UU9Vu^KuK+X__c`F|U10=fDkys>C{iKbcGOJCHH>4tZXO#Q?=7OSTkR zK~TdT5z;yH!)c?+={i28sVEXmYU}R%<#}$BqHjg&*jHhYC#(C!pi0erX&Nr34`MKN z350}7BmVNjA#ygknrSbr@xmy&z~0P18o(s`D7|v;ES(6}^{Hm|<}n;7AP6l6fuLGu zTNBWIO3AY@p4@=4TaE%=$$O!+cyj|khQ^8ktoWHX5N6C8MW=~%Xs>pxE8IuYh+-PO#JlPiEw6%&vC=G-Hsw$y+ z8C13DypP2MOl+>j*jx9J6W`v;Q>Z06It=+qk3a-=zAp_jJ}PEIh=jG|VHCO?N4;)$ zMS8btT9HC5BC!8gKtKSh1@JoTderu+7O2AO05a>2+0({@*RfwYoY9uy!ur^I-&p88 z#=t;rE^i7RV?2frg^CQ9HlUX{M7siUW3YHfT9d`eE*N^e(?lq1M>;If{*&BX_{yC=xIzGK*+cEA{g@tWzNriWYpkWv*j=-^(0 zi2@|dRt-ipmFZLsn(8zz*gfr)|Ah07#2@Ah97GoV^H7Revi)#c=*Q`gUpF@y_{!)_ z&ph;#gn@JPwC8Z2oW{W@u$y8e#W4G-pTBsb{fC(X(FroirovPiRlhL2<6k6SM*W~s zek`{&!Z#JN-O(8zF_9e68xk?PX>XMuH}U;ogNMeVkjWKMT;i9`c&FKO@JRFsjeG7~ zJSYPnjqStP-^uc&cWg>rm-FDxN9bF$IREpfs4Q-8cFMu8+B=u|`wLPY&bU(wxCR-& zFV8`6uF<$9oyV3@$}T(LzrMTsy6nOP*gi-5@BX;~dw%dh5M1wblG?SiJNMu~8zq{* zzk{OCLC^3k-T&U!-~ac+m6G)(F0qr>e?RD-cUW=`b0bRVsrKDDx%az&UknzZ5+7%}%h%WTV$hzaDEUDQ*UPaqsNQ)RK+u!uWz*Wd&nEP)JH7h> z|Ga^}F3NQf+gEh<+|xf_#ecp)eg^kYhV;S2Z&%SPDk(<~tklpu7EV6Zb93jjzpk+N zMpkHlIIPbq$dBxO3UYP09)7klOUTZ9TyTN)B)w;{u=F-9#PuIv?SHNxbrv4D4evht zf4%$n5~40k=Ulk%?0g$|(}kemjuz(hoNqFR0LQ#`!}*Za|$ zbjBb3u!}I!ji{a{KfQZ}FLC?-ADi#@9ezIz5Bw(T$nTx;*H38&z@DQ%lPbl$vptSK zg$Gs^vU_i>lVN?0>HlTR3_f*Uo~n`-3c0rDDYQ)w!u7iIGVksDL?b?|r`pTHZ(Z({ z4~YNz)&HEQ-EZ0D4Lq>c@qo|&wGF(8Vb8tCYt=i0zOAi;9ytD?$%35Mk}=cHXa8_9 z^i6xBnWD{=4~*t}pW+BBT<@t`_UqqUeN9vpW~_hWv0ZO$zkd1uWk;XB;SUdN@Z@6f z-fiHbKp!P)7f^C4Y3K9nN6-T=!W;4U*2@yJ_q%(R(~A&n0u9aLJ=Q%>;qv(mT+ei} z_0`T+7o|ZqL2OCNgyvM}6=Ze(&$s-Dc&5lf_Qrvoo$>civ0sHf=S!^mK5%Epc!1cNCW!L|Z^z)SWq{;G*HD>a$3XIMJ-) z2i_{^sGpjA0CliqNSsdokQ9aR=0bBB=sQy&`Set1l`Wp`^&qVV!5+$3x$sjXVdnLz zs1OAO%$#WgRD7OEkKDWvyI#ptls0X7MJ;c(lA;Vmg->=hLluq+w6p{?7*;R*ahCtod@Z)}yN|R|aT<&7=&6*T<+L2qm?WfO zdDn+;gaB}1>(}?^LM~W}%C)Ib^l}Fjh<&X276+$GT53cnpY)cJWR$)LWu2vxQiKqz zOPZYag$A;vj$`!Cz^I(Z!{xJ_;4hq;sbntFLJ`;d01r$5GKd{zAvGjDS_DP~WY*eg%me znLFn%)*XyJVC0Z*F(8kNU7egqxy&S5dg}luYejnW%DNVdRDEFFyT=>g92^2SGJ0u)^|xmkd-=zcBR`RXCV#=> z)F*@k-n{@$6AZ%+c=SV_udj9+4G+OWIfP~eW`Ab&=kcMr@zQ3j5jNRSA2EJMfQk#e zpu#?onPS&73CiP%?AHW!Z>zczEI=FV=#Uv40YY~`mt0t-Nx?@GW5!lrZkRwnN5NV1 zLJd<~81W3L`#H#-wr%ALE}G19 z=>#@rTnSsvw5;@twVzwq=oNDL7W^=;q3&n#Co11~N6v_@ISK0biUt(=g+j`0?+#@s z9_3!IZR1Qg5Nb=rJ3cs}xlr~^T}9UG4ta5mMRG!Ne%gh`tOn(_(1)iRnOwvQO!}Di zm0jEG;)BCs*&F26Vp(?9eJ}!+{kqH2w&XE_`2(M^N}EWxn;lAMs+6vEaL$cYA)|Wt zVG+iiNH1KqZkFY#nE$?wx{@Ih9)&+<25Gi=)gh(33kvavP=74{1#wCr!k-l^?W0){ zB~c({I5k;HFEK(eJi8yoU{ciC^5viSkP6FNcav1&J1RW9=PmrX zae?f+U`bg$68N`uVY78k@lSbEeZ-!<-j%99CcsbV;x_ItLH~c5y0AubRSkz{#Y_)R8JeYm{t-e3+yuqXwL*Wnqxbfv* z1YWIz%^JoJww0!^w-!TZyI(WTk%!+=3twDPRrfsKD96>lVQ!T&`X)$QryOncJCpGq z3i}4L1L`eXEO}nT+qNKdn%eH@7;JF+1i6ecNYkMN66ePiZ!^&%}FNcurpPt_~jYzN8iQT|Mu`*Q*w) z>QCi~aFsS62xbp^2uj60=<-~&dXW$rc_?H3N>>Ji{j=9ga+C9xD)U71`9~xCobmYS zAn`eV$8EoIH&Ox<856|fD<=LeN)P={hc zq5wpM@iaYqu1!AEmT<9RGlEm@@n2NOR$8lFtrQ(wfMmF@m-#&IM=@f7cqKvz2zzVkH!}~_r%QXC?}2}Uo`w3>+hs1#x7JD6otrm zV_|rGnSti~n;EEYe=wSSdz8rPSMKPsgruxH`t4AZQj)5`QGHlALr zZqCrFYo$>6r9p_rO4^zW>DN{7`AH5~;|(J`?}jD`X%c{=?m|Pw#kLU4O&N?lIi;*& z*^&wc;i`?-F+o0`aT^BE!5N&?>;D8=Vb9QXkp814Sn&(j4yi5AL;3bTNiFKx--T{I zb}PTv&Zm6hfh;qc4M zj(q@@EQ2!M+zOT7AT)BQNdZ@z+914Mu4{ON7gXPMDQ-i{1{b&EJcB%fOX^a*XE{!| zlw{(-jEdL&EG9NJrs1u1Du=Q`&D0h+G+BjFAV@*BO)rei$Vn~h$HJ31W=%Rux!$ zFiGaUpAb}A=)+s@$h~aU)cx6$cjvv7OeOtpe6b|1{HVha!*)!#ZrChy_={# zwNHHQ4}&wEIFp4Jp^N26y8g$cOsDYF^ISihKrU7X9cWj0nVAV~{&d=2b}ECAlXCuQ z*F&n>uz(T2PZs?5gI8K^o2Vp7&f8n$QP-wSU7A+!`Y0-pvYb)*b^fJOF>K$#6>&TL z<=0*tZx#xh)26}F9fLk2+raRKrnVO|XYZYI{&34Gm07vXA?wh?mROycXL^%nH8-WAtR6QC|h0b6?hm)cx+k@%w4G>f*k;X2`SvT$rjx-Tg`v^-t83m5$95L+dH%rzgZm6*TAdbr z2UJ5xZ8FvkBVPBNVgG_hZk}dU%z&S}@mh9oDWc@(SqRFl+MLICBAAk#v(B{pt_@_E zX#^h#p#gi%7-o8zL~`!O7=+SZ1Cz$H>X0Y&NBhgg7uZ99dk_Y`ZeAZneHCfCw(I!m zB0j=vW9R1TkJZhc@Vj)`?R-sP??~x8d6)+<+uwoauiR#pjCLnFG%FE8C;F7E^vy-P z3T92rIW^Xm3x`z%t!i)Bm_R@5oN%2aJ%Q`1bA!xUt5->G%*|x#5%A8;cshU7BVa=S zdMV6}S@pGbBNIC{l4F4$Bp6})DFdy;2=j7CxS6q(w0tmE^{^PxyTbG0&%<4n2?D@P zCaw_8Lw}-j<_sFWM6yZmx&m{Z1nmn}&cr-39e^C`=gc?)LHgiMp|+JmNwo)w74MDy zYhP7*WBYwdl54Rma>5@?s0-3L?w+m@y3BA+`uV=67sY8;(L{<`@Lu=h#3LF${c+#H z*YvqM(Gnf*`$E(#@WqWHsk-YJhnIy@oC1O&LgwvL8AnZ}( zn{fdO#uuZ~`9%-DiuU`0w-cdlie+hz^>kAm1FXD)pqJ{(Iu2w}O#{Yq>afLJOr z#f7ab>@->g{hOq`>Uf_wW`8B>GU7ko$Z|(G!f}X!<{-js4332B@K*ZxLN{GuNJUU( ziHE{VRsLo6GVo4fCW%Mz@g&)GdIGr5#jL2Nvq$J6oRxdUlPT=brW@bs+r6(lhJqSa znXb1yOLi$BxyY|KkGs&^Un=4L6naJQXi`-I?8gQwheC3S`0Zqt@a-gr@xeSGr4PhD}Ecgmd@BY&$m z6q64|$h^|%jn*bB^3r;2S!v2TlMX6s<}=ylWpy=dEH|PNe=`8+7C5A+Xbatp;?pi5?+Z2;8i^9A(h5*_4+^OkUP30lEPv1NzJJidjzjnv3 z-DNxy->PIo*|U{=IwdZ`_R;W$Y{*IL6?e-|R@3{7joS`#q>FD`b`{O@{lQ`E==&sX z8yH`nS1#3QeSNt0b7Wb@KbJK|Z3za8g0Z~}J+#do&F=E{g56bMrhniZo;A+t zcl$=cRmxEiakDr~Jk?p-Q&0!1Smu9Tvl2tA4V~k@ROgV{(+8{LU3D^8@XS?-k5q|# z+D0<5=XxazZjv+v3XLU(vJFVOK4U-T8$__b=7@<(0ETUr05hq|njvOiR%W<%j5>YX zbAd`QnQlN#)Rq0>GzF8l@j7)IBgZi#nudssGlGF}j?#`FBCVcK54>$SZN|46Cs;1# z^iCbC9(!aV6JqLT*B)FfAUunqFmj)LDtioI>Q47WyH2w$uq7V%!|xyWM>UO=Q+xwT zH1ZFgPwN$9S>l9w<<`qTm{0ssc9`DC?UTX*FGq=!v%%rzVFW?r@>n@pqx}tQ*bnlp zzH3+Y104nmkGq_eDn4&pC||n2KIkAm@0N$WJ-v_hDz?`%Ei*CY6}41P`juxK_z@YH zN{vnebA0MYA3494tw`I+y>^ZL&Np1u%xx4f>pR&1=JoE~#{#ntU$8l}Qb`l^9Tt}D zl>2Jl!dQB-yu*<7?lJ8$TpcaE6fDjV<)DC3Y!1$Tzk|95-H7ItQf!qB1%}AXy2Hh( zNv}53cO8UWJx)OjH*i0 zhLs60&r|BsskeJ&02?g!XL-Y=h>H&%3k{bDuo@6lo=SEjBHY_hWCJo|9cTX+S<7GCEu0YkhqU$0%>?ih##_yK2QsX(i!^(i&mgcEk3Dy!vv} z0rCbJ_w2~j2;Dlrk<(x6DE&=%2UW9=2j8R2Nn%Q!5t1$DBjnOx08ims&5CUWkk zH!qJ^sx9@GTCAQSb8M49sXfG6^3IQb$;%Jz3&fJj_x`y3p0j?o+7@4`w%;o}@ms1~ z>#xEeZBzU%1>E|5`p2TEnxx1T$3_jg@7KB?Z$0hA@ubvgGh*^kb;H8L-Xf_-?`7A< zuY0s^Fl^R`2xim^Y3t3K7|V`sZ%|_>C_2U(_+Ks38eDTEOn;zeq^I%4ZR1nl?e`rI z=Rd7!;69bpZv53nXzOrWcyCK=2DR7<_%kJTstk?NxPpdd&_`}fAjX`g+vpcN<@U!j z_c}qra%Os+ct1P|u}xavKeYe^YcJ2ZyK_)mIT(IXB%K{{E189Y=5yQ|t`d@d%5yil zUIh&a)(=>_9>Y?Uf5p2>*&z9tfN^%BqHL&pCfH48A9ukE(r>C4U6lk=tL(T4$1(LJ z&l+>_@3@}0-c}g+$Cz4gFNOy6|#3bX2(Ope<3tY$`>7Z-N|NN4gbB z!w9=Ud7Ekx|Lpqn^0k}sDT4A9(=(#jYPVMdyw!Yyfedq^jc(fR-X{re`48*dSUY8+ zRr1Cssa&B&<)gp^QU9sSzKA}+c`!AXRDmJlQko9Mwabe299y%o&fVmLKIEs0e^C(2 zvTtLGjwf*XTpDi9n95)#yev9GGC|YOu;AaV$DFaxm9f?xa;Mcmq7+kB9r*QhxFd$JD%LP3AyX+z&x}T)sjVPaA$pHNMoIk zu3tTGz`sP-`p}%_bwfp>rRw~Q9l={GVYdaHo_1rQAm6)Ft*){)niU!Kvyd}AF>Fn` z|86bT{K1`d|F{L^a6zY9qkYrIi3pn0^IDeV(ikKSU3AdO>Ci3ETO?C8ILy1%zsT6q!rfV#O> zwV^u&D=!;d0=?fw!dN*BJwrrAJ_F$$bMa_*_CxZ1*b8-%=a|%qSBOaINFyc13toJA zjcuIOSF`25w1ziRFnhL4P!_5j<9e8t{Zagw|)SClXf- z5%PNuObQCSN)q(v&GvdbZw=AWIVeQG7;Qw=RE`jJiC1wo*3{)%fK^QMp1E=H;0s5|}1%oBMD)7%&p=OCdkr@KLkpQelL3BRjlu9DE$>FeS4{bJn1?(V-N(^^rfM-E61 z&T$ub0~h@SMaJz|Gv3yI*I>OM-#_O6ywhI>!-4%&p4e3s+RppDs z$2MN?CHm4>RU<(V;9^?-ba}A5%Yc|{V3zzX1%1%PG6AlLs#G}%>icFVeCZyYo+gjP zveYH1KuNGgC1Uy0G?uxFlOrO!Z$4uA2)>x9I7L-64TUHxl#^}?HZe{oVR0n{Utb`j zwdTwsmRHiM*mu5Exsqh33RvoeTG&le#)!wL*U@(Llfc5u;&)|KDDvi0!ZdhKhR z!jN2^#@j%|h^t+BzgKP+=7c6(7|%&_xhM#2oAl>j=VwV2&e2c3OMC0?eOL9DOA&eU zinXxR2_C*PVnnNPQ}kK7^o0sCE;&a8t9+ zW_Sg9EGR~pn;9vrgqGW2Yp)x`Sx`k9K9DGo&u3FhCpxQTO~Pkd6rQR3#nQ61>!a3S zNboB6ZMN2@Ov#@btZb&GqGV4kkV)|0ry%>VkNfIOSM>GkTCb}tE^tgd_<7CjGzT|s zWrhvTH)eNVOspcCVaNwXHg{_z<{Di;^1>oq?ZqPlNGk7N?)RifD(zVUaPNmfDL9lz=k&m zR;Ab?Mu?{RS;+k)z7bublVEzm+x%3|gd63<_C(fe{bl|9)NS~QYM0#2gJ)=J+TPgl)XfgX-0R463 z`dX^VaH-3!7JM&a_7V1B3{D976FUij<3se_g+`SV!iA40a3tn(WZGjL*fJju2#o~m zJ|JEgw)sfBAPDH-Z{p-$@dcrA*qfVkJOg4ACv_G72;E1-S(^LxvAliwbHVt58efL2 zdx|*9B?mo>An2a+u`@i&fC6z0- zs2q24oqv9cKlAh@mQcH!>bWu@*{5$Ak;wGVH!i6sF%k^LK!$a}AXPt_M|*o=R+TvaMAv~qK6;*!uY?X`;;Un$g**wZh#E^K0Z+UU5PVQ^Wn z^mAWtC9ed1PI+PZ*evOyU=f1Q#25IZipAq`qWL}OG+7n(_D@}0l}a!7l6O^2Gm1=0DD; zvCGDt%2*}Bp*6qL%Vt9%M=X)9%x0H=?Y5&G#}bC^vaoB%f6q9G-=_Y`vq6#~ziArXCq8biSR^c(+MsrZy;7yuRPjDR z#>e!IGmXYo&VnjQ36FhxHj?kz7mUY-(o>Kt-7X4=@z1n_g23wdgYZVrrSMKovrYAT z-(|O6nBCeGdL=4AQMuUatcQ=d?`gm59vkkzMCgM}ePMbKhs>?yE;R8XuSisgze7NWh^l7Q zz}Y+2hU0YoePkCEXsad&qzKyTAB$ZJj2k_Di=MimISEKoF$!nD5$hbqldpcvRy6hX z#j?1>Lvm`8*=W_OcnLUm_2+SDXBpF&hu_)Xca!E79G;`~vz5G8Q;ab2yja#o;eOZS z1G%5vpO=w&&BXXPb8xU78ol|wT5+Dc%kVgn*BK~&OyW}4%!(3(zSAqZ8V1@IbCNmf z_594XnibbBr9{gexYj9xD_Ovf6ePyKKab39j6LVftXVtxYWCHO;el^(5PcC9v0r~)>(^&4vYO^BV`%c9+mL4Wq$L*r9r`jqm6<1*%FO2c8cq=cA&(Wm4y^3i-{(CXqd zPQKFX0xZ{!8KC?lS+5ETjM-8^Ddb^t`UL#u4 zIa}HBxsE#iw`5cK^^}c9TXS=n>%G3Y$r@`m>yO%`LKhU99+q{=;7+|0Er6%0-caV= zj>{x9(BmFYlS=%Q5y7m+=A#^$^wqQK4EqPXvtJ$7#gas7&iviU1@NPn6Et(HoT%>L z?xdH&-grd!v=3!$vpp6ayQuIJ+LXQnw+a$;5b6HMU9w8?G*E1MSnjUNG2^r~`1u6k z=f|H_s6NY3OLr{G?eCm&mAsO1i$rh!B?jjPqcX|Gto*F2B#O&o4_lsEG!2RI6Q035 z^jcu&B-5M!5rI$ne0pZB-5a{WXGfH9rxt#suds6p-ROZK(q%Aaocr2RJhcUJs$3C) zH5dVWYAanqEDA#hmxn?y9E|Vk>T(~^FURD+FI>FH*3$Scyy~B&t{F zX0)LeuTNiwkYEt~ySFTiDV^2n_fD1F6e!=vM%`wPb6exvgNf0Kw7`wP#g?!x8KY>` z$_4Ad#!KO&oF;?sS)fMptNP@Sjq!4!VT2J`ggHS5=4RZY=AniWvI5TmE+LzuQT5(! z#dbg88i~?c6QsbE1DY5Q@+hY(uyl^7aMw<$m|>iJZ7PMgAq=qoIB&@!NHMJ$oaCFR z?IlK}$B2>Znaxmhu_9Jy1)gY`<|+S@OExWX)RgA+FfrQ0T%&`6HXeH;C*DypJ0*z2 z@FMB5cvN^R*0NPVzpNLUyq5}uqiQY7ZDjE}WyxO^^G{C2XX-VhN(>x_*xHYT(cVWW zb=B|dQc>JQ95{E>QKn43UwCT$rVc9DM%j~3{*13klQ7H8<_X1yI zfQB_E+j%ZuBH+2>kQI!-{kkOTxVB)`*(TWVDT+0WdpA5A+VCn4A!<7to?I92mA16Y zQhDJwJJ6kRtzjz`6gItF;weLTE#;AP^ryvEHI*!N>TThnqxt z^Cd^2ku|5I@;a^{5gR1&Lm7D%OW3eZu-VJg1hM7Ke2Z?h$Nk763dvNpT~-MD`6Aw> zsYiuNyn#luA<%gk23F;^6Bu0O=-uC$vc?43iIp4717wd(=ms_Kf~}4q1F6uxm`OMV zkBj7rZVFcC&j8z(r3u>E_+adVcG7h84Dj6YbHX1J6`l(DfID8QgW_i0lDjk%a$IfvJx8ijUrR#T9 z*YG!47kp^eGNG_db(m}{&iLr!&4d+@c#`zxPHLp5+iFyF5)y?`Hl(#FMV&m6jdy3>JbGfKI z*Xh7F_%3(bGw5i#ZP?i+;79b{c0ZlKP(P^*Nd}!w;;s_KaTlw(OY+6B)2X@7xo|8c zY5HY(^xsRyS6M|CQm&6BEa(az)h+ON#&vUxf@yfa+jzEg_GG1f@}yK$PtB*e$Ch)q zmzQt&^BwnX$5vL(^@-nK-2izDVsymKro{5YzvNF?-zQE_F5X&GxN)b_O*fHoWz!Y4 zOaes(&I&GQ^;lkJ>$DE%qa9{;Xsy#aB+@hr9zwI$a%!&8*YWCFcOQB6OtOz2|Ls8h zso3jteG`$}8>3|xYcBY|3LExcJZbV#F-qw0DMFd3hmavHABn;I7dv9?1)%wpQ*Hcy zLu#TV0oCMLM%y#y0BkJW6oo3H$=4n@cVdh;oj?KMK>11X%U2}u+UeXWiG_@lfr(Z| zZ9M34Y%76*{3KJJBSD6LkbvtALG{T@B@dkm;ju*9ms^PN{{wT(<@^(`AsqgOZJ@eR z2pO7RAUplT1`9A49F9}Ci`@psjt=?LmadIct~yM=7H(KV$Jax%>(z&haBP7Jt`QzN z0msbH)lg}{=jRTmm_ocXl&Z%uY#H64u9ps2jc17Q85mR&X?xCg_|c!|#f#?oN~&MM zSbw-R=ofKZ7B>j$3hVUdk~!ZKh`o#=&*yt^z< zk43EN^?kjs&QSL`_qqT0J$`?kKYBdKb$veX`P#4Na|&uqLKw3V4q;4N z=DY%^mU5xl&mXl8m}&KCRK!ZaV$l z+8M|6k68y_Wz~!7Hn@=F0rJ5YRmjLE+Awn}@ddhk{DM&w*2bz3q4CrcxbxkB`*qMa z?pbx)2<4m9#RJJsBl1G8vuXF8(zA=#{P9kNgJb0P7!2h@We`S13T`2 z%oXWOo0xCTv%_nycQI7aP>AcygshzGTy(cWv9MRF(^7Y5na~|B^{xlc_QZ~q21>^g zvn*U6$;*qGgq~};73jlc=)`+QESjSq>R~Q^YOGn8cjj!I4PL{1dyu2CWTzu*%Qus* z`P}wRee6{UU)()GVwt+iY}Lo(*3vX&$dC^R2~kx1i=3xZHzMC=K4t1Kk-mJX9P_p2 z!eTK5bT&-j*6$mnQ7Q|vSK`{^5nSf?J?HqV|Db8{Z}%rDI(=i>X|=xccbm(xM>E{B z`{<_AXj`ez;B-^kycGSrS)S&bl{RjkJyEo=lUfEjFE1tO$-gzG7$e41YF62a7Mjf8sq?n|UKUkQWMw1ZgQTsDgneB5x+pZ$SkaF*NM&?w`Q z+xhbjkzeoejN(qAx{p>Rj#}5GS5OBv<4EN_g`!6*h7?&Pg#}OJ=t<|uSq|_b2WQUq z%;)*ss8Sv`Yn8!1)JQ)7#aGuE9ah{UL@>WN&PA}u+znaQVtl5y9E?9RlK-SPK;Hf# zG5z70V7*1rFMu&sRWkS}!T;MkwRp!Kq=O)|K2vvRPbVskYpu7b)1BQv%gXZBNT1x3 zzTdvIjn z{w_-%>6ri;qUndhwzzp6`91IIyBn9kO!0-3a)us$ z{={OQ^KwC=C6AFec}G*dDgV~fiKip99i#zcWF2|2sxxe%pJP1F9~epFfBN=ubO9Ug z)L|!CqGsL0T4I#KwW*B`mdS=qh6zufCUP-;DSX=h!K%LchA=}=_}CQCtE;;-yZ5OF zOKxo<+_3?`5e)6`*_)T)@nle**@fv75yOtj@3Rf zI|JnVF+#&Cn}Y2Uv2-qi3dN4RotL!vYRb5uzhYTZ9XUQ?SW>`Bag`*^gHj@U$p|?w zV6zRh2IXqnF^s$D4VZ?X3|}N?d_`WT5jgygeS&?2*e6B~vjhg#{vksZ^MY$8o7LSW zC42Mcb8ZQnp|Hn`i@nG;eD%$bv?Ek@c2IwYyGDDX*aF4MJ7ad;aphbu=JGPR5>yM3 zg%IcJ`O@f#J9Z;p%PEN?R9C0igJ$*|rSB{C5M^1|;$zQF@Fq@_D|AnjI@Tboop|XjR zOy1c-{Ff1osK$}cPq=x`CO=A+jy+B`G#7ZR;7%7{#^ENb`rP(8^Gu#gJ%S_co41OO z7J=l<2R}1rZHiwmx}H=>eY49%KRWNNrvYF2hZVb!QJRiMsGsdtmba|+% zBwm`n6|ZlS?ERq|DVGV-$d_*D#as%M+^frO;2MV(c9(uJx#cmc4M3cTlZ%V+w^^2; z?k2Ma6N?afHHLVi4(BkiBZR_iD2*fbH}77)Z)kq_)D^K)sz(Dd=FZ2vpWqE8ccp#m zgO?g6vfu7-N8nr5;V}Q&FOk#3G&{{2juSg_C<{E`n_GFIZnnVy=xZL z$LF@qy>~I1lb?7FK@FU&;=&`->zwBzI@{BXxy>~eFA44EAFc2cS5v5VJM6K-`W2O< zRl+~v%fVa^$8B#tgecea#U#Do0t)Zybv8l?0&;?tDG1a>R}gF3 zCVmpi$>qtNE*yNf_^yYue>Q0Y(BkfAwSHY{X2Z4eks`Q7W-8cp>?O;W%U66U)r1Du ze3YGCR<23P6PzwZl@OIz+M=Aqk;(Tmu1zsfxpweN@BI@T6Cs1w=sQfFsm|QG6R|f> zfi8tsN^9s)N!7ZDqn!KOkdxjaEP%A7Imvx9efmG_LA538PH*M;zKcnX)1-ZP7@7zD zgwN=M=xfv%I#w+OmdK?htc9doJILl($4o<0BzmE_+s^)%*i&=;q!39TvDbrWVVX%+ zWdYZ@-hNr-(Q}?bxks-`UOi~o&=^u=q7c#vK*dfo}53n7O6WqZr9k#rPOIP8^8`)&;zKQCW1FBZQT zpFv@^Y_x@N!Um@=)mU_pZ7>d$b%Hxiy)HJvKO)d!x)7AxA9ShQ_p3l=5j7s^x0vj% zc;W1sYm~~k-shNmdj<;b{?rXBjl0PXh2+}}$``QJeY*qxXgBb_k+KZ+$0X26(Ck0q z1ks+r!M-mK54_$-T8OX&NTdwq6n%dYEm$}fZcISxN)yj`ZT^9gj}k!znbDy&&be4g z54Qu7b`l8$vwr7vS#MqlP>AM|B?`GqlXFx?qsl0tDZJw0^K6d5NLZ}4Qm9g{w5w&H zu1>B})d$?G_Gpqf%;J{^bE5p)0_adbk*0}rc`!v5>#g|tgWondI4I&CE^SO zW4hwl|HPVN-U-(#St+Ysp2H17848$#GKE|jZY^h4L|5yEs%2LYAjp6$fiT(P?B{%S z2;7T5mUB?iJyjB*V6~OjJY!*tCw@@&nfkemGyNId9G2{3r;d~E@8;;s>bg1mRI`-p z&g!f{y}-T8!NF6Tq>y&I?ixUZPd? zBH()`+!uL%l(mg7OMZG+(K3CY$snChY<^t2IkO^ znlG1x?8>2&Asb8(b+q^t=lhoKp+{MnB7FjxDFT1K&~ks|W(|orG0T#X-mP?_VA1Ij z(dSme&BsRWOV#jpFuA13YrUwz-B)fYgwR6mqS;z;cr%+ZlNFU;-ieMXOYw6a5sL(aX9xMLg}zo7@h46cQJM*JiUp6? zZ&XIB*OfHXgdf>%-;}6&1obSQ1}#xtNhQ!gP~-IGQ_Y5N_JbuwS{iScb;TIzb$_Xi zE3Z(Ad9Og$oYNuCaDkUI?zf4hEH4{1(AnTxt=xAWNi0!)%^vdlrfHe6Fnz&mge{4Y-N&wAmXW&cqy)o$;JI-m+ zXh0c&s)2NZJG1xecD=hQo;@%?%-DB-b{XIXz zWIQ=12ZfZMj}Y6Kk7HPetLN6LuTMcTKu{^BaJP*wf$R<0yZ+2%N(~AWW}`-m&(~Z0 zC67PEAL-on(!DWd{|Z2jWLYh&3~YabBgb(Netc_YPU;D}&B>+>w}OsD?wZCho(?2~)# z-}8U<3*no2V|Z!gNFlZH_2RO#-G!r?TWNaCcr0NwM$F>))bpB0j)zchj+U2%ICH^~ z4~05g?WvdO{;nsK--w@YAPtswCP7^Rr$8?p{>RuY=|0#s=#=Za3wRP3re zE1SIbiL5Z^%gu18F%g>jDiT!P^dxK!3d(DbmeM8mav$?fE$j@(e8 zez&9pTZyKwU5u?XfpDZH+trdYeq==r_Fke=ZKegr2HgjPs9icv$k}X;H&Vu#8tc#9 z?f>qPa<}*?6_||btWjMTSmTLRxMR$D<>|9;(+?dyB=v7R3-3=0rruyYJ5LiUpkAt>7}w3quG!nk*e*~^IBHgWIXW$b7XsEC!@-u_F^O{RchLBNch?ne&tU&jkSjw^Ofbpk9IA63)<0&O5*mAB> zxPI_Zra+mb%~@AkQa?wMr~O%6L|Di9e7=4El2+UnPv zjHvoe`g~-wgGBOM)VO2aeI;d2@=|g;rB#}z{>xR9)UrC4CICt78jkgkW{uW0V>dA> zhE_j)KkV&fOSo5aPk-i6ymb#rXXsT#TVcc`pBmSJW7%M2U#;6W7nu!srW*3EZz^po zq(+1pEO?F3jQC$Rj8~{C+QrvnIiqO2$0Ko(ZIE1Oi`kM}N4WFRQl~X5Szk2gK1P*+ z_+X)+Y`@h~9x2D#_i4CRYb+iV^};6~-JCnakVedF`QQz`%O96AcR{4%D$h0RiU}SY zjkmRP?_?92oauE^Sg6j$TGioory7_BvmM;ToQ!dbp`Tz7%Dc4a|6OfzGAYwg)GA_= z5@!>e!I!a4gUYwy%n_Ckgfj;a~zHVMza-ccna0}bbf_X1~UQhb@n*Bo8zLaBDOY7IJ zk3S?1G@yAvdLv_v_hOWJvHPji`sn<&mYP!4n}ho+H;=3KPgBqwfPBTCM{K~ zTDPB2k5mKMN41yZ=$^V?pPN+vGWboj19VAsNXtPx8e_Y36IxE|=7Oqt$| z?;WyC*MKwEl-GAioaNj|evVOTbn}Df1^W|KI=xHZx~DHnCvE|D9iv=oNvkRJ>rEZM zQ#YerQ&y+Ak6qrlS4%NDLrRQSO#d>irt5wjdY82;=sdj_kZRqg-P2a$(sXh(kJ2nX z_nze7O-XGpr}-Z4>Jtf)^Nljq#5nQ4rf^CzT^>w) zuK3jVg;9;t-#RpXHM4Wxt9zxpkuAcy?w&!V_{WL<4%ZE+8`OfHT=!=md{%!%Y+>Vq zy21VVBfJIJQ?lSAO)&xI!xH19N*8ob(NKCX^DBujcV&|eucJOT{VT=177;CJJu4+D ze@gtMxL*?PkblUXB_^F1Qce{jn2`5bb>Xj_acaI+J8S8P-#t_qY~pIlDx46&FaCNy zElyx4WDhVM@hy_+Q}r2B&@|(@sCOavfNi!TeRGLB-uUC;=4<#uPbL9OVgO>hn=VIl zU85?ZQI%DLMhNYXurh1}Xcno-ylL231e3t8ywCf_7~+>qo>9_#caJQ5w1MDV;85?8dUofEpaXMWn== ze{tolf+R(B*l}phc0lN24zK7kevo6#m?D^D=MfW;@3B4Uy=c!l`o?(84>I1b_+>u? zXz1Sn_5_(PKEhNu@ar>3A%!Rfw~VMKu3Zc^1r!V-1W_;~60!s2AW7~QzQ*M~cbfxO zhgugP&1180S(I^==uOc*;Z~GD9=NrOgaGjI7{l6+sV4x550!)*>c1ZVl!*B8Pp4Og zVoVeE27Kshs4GoI@EugK{Yt0^;v=IdFJr3B{cKN_P~?an!-O40&G<1v}cs@eg}D4hz6I4>O8=Ly}Cjh zk5?mtgU3%QxndZ7+*~ahpyg{^tQ!;lT)SWJkgYJ*NR5*zw7&QArARLT$gZ7i4n8@? ziPI-=9MBuEhzR&pT1n}4^f7of+!%BoVMF(0l=qeRD#6`blZ8XLIbg~4LxI*Uyrr6=fuPW|-iAD7XC1rXIFF+#LIg}NzW zM4Go|v%e1}2`d@T_Kjt}*CAs4aY#FE0sJ^d3J`M3{x6>V_!^4GfOb=SC%E=En6MLA zK(IM^n~)kKvY%f4!v;ww!eK5`O;VQs@f=9w!(pa06zBOqn8&gxD|}zrZ6c4V@~2n- zsJZ?)n$h(X0py=gRZK5yJTfLDguW4X8ve%LqBW z_kS^}h=?$O(5P?7)pYwu%V8H76-yNtAK`xwMs^{iGHC5|VQUc0`aAYSBEVYuFllBT zVU7snu3+$~0+Ofdq!WHWB7bpkFneX8-=HAz7^TIj9|2SC6yRO2G6V#_8#KlUQ(436 zoDY3znADaF0MfBvGxv0PfAmGyK)V~TH4*LO%{#B{B>o?{&mGp&{(y?puWY0+Pv0m1 zh`&2@7oKjXWqwT?EBtGab(dL0^M$_Dr4g~@TVCvlXNdW=v$j{#$|38=?9FZ zlN+UpMpFQ`AjXsXmc{Ko<8$8fAJ=Th>nWmL@OH13ZB}I{EB$7s{kAm03aBR5I5Wl+ zYx>a$BJ=mD5%?l3b>L+9S3=V$&Atbxy8>R4>!I@eE5Hq~4?M-`Y~}~{kYzdN0&aPw zx~c?abq|6!%+@Mq3UNkojX++bCH*Y(ry9bYTT)TQdhGG?6uZ8%j?oX6r(p@gb=JS$ zbn`p-OEeaTnb_MUh5F$ll+GUy7l}2dVSKu(SvynKD8;ikf8uiIaUzx}2niAItBtJ@ z=IE3HDn@KoO?B7rK$v!|ZsZEJfh2kr*Dz1i)8(fpQNmLTd_u9%5x@i72NhR#CDu@t z9ZFB6c3AVWo!kmQNKr-VyNzc<0y(|Xb16WY?`xKVHf_EcD(OSjDt^jBU572fSxt!y zCI88#|9zFu8Il2h^<@j$pSFlb4Awg=zUUY`cDIg^KxohUQa5womQezA=_v z|ARLa&kX_B92UQ)d$!CY^ESQWk2X#P4GL-nU-aq1t`uhW3|#DtzTH#u(@@U9 zm;kp;>lN$@KOqTt;#=8O6iUY}9wSVR02)X^_)mC#1TqsEge8{1wpb3VqXW-gG(BY) z<<_6QGXr1_$xbV+L?8FrIr0sTr3EAQQV}4W8+-&n7Y16urzRRIk8!Gf>*jO{w$(Id zoFy6I(|nfj1hlrj&_MT^hd=w?Fv5>q2!mEuNyPQ?!e>_c1O|2Dw8&>e^}aRR^isQ~ z>rZYGGT*?v+)tCYzSMqX@h4vrlLIqd`uL36{(Do#kPnhFa>Q*R`XzvZX|R07;qf~bKs3N4HsjZ1{ehB5E)L+Y2ySyP zghxVc4ssBGd98+95@QH-$+MqOaTFDB{ zC7%E8DG!CBsYbw5vGBESg=tqow8?Dv3xCw_M&)@3V|FDgYF4A#cX?WlN;~zdLv3xi zbgV!e&`~iMNQv={`MxTmwre=Ln=sFmdUZC@ngO%4!Z$q0jlrGjs_pyr2Z4^&j^1Yt z?*f>D1%vj{A0}>NLL~wE4B$6wivjLKHF@@0mz8~&Xf??dPoPY+QfA2|Q$^}@zg4GQ`5sLil@&Tq2PVs8g?0Q)&{Si2fTW4;HV_H|fi= zDVeP~=CQUwQ;Q%A$zGIybIjU@D9BNe%A)!Lkd}0;$~t5rFYH(kO4zyDc^gH#F!dA=+t+&`ebuXYtjaF@)ZiizmOT7blRxZ|S3kt$21vbDWM4rf(CE`PaBor0m!S%8#9DJH zs(L8z2?#Temx=z2ZX7(ILT9^?ye?U5&$2E)iMgHy4SLZ>r_9=nf_zQeBRtL;d9r%Rk=2iW$@KCv1B1xm9l;f0;E0&266V-X0T+z zM>3{4Z{D0LiUAaN+-UMbab?!p6P=d@m--!&qoumXQDeO=^fmaPfG%cBWp&K{orp7- z5mlahqfk=(T!Q#XO9)zXDvq<8JN8f&4Xeht^3m`~0!?t_NRT)1(z+Q=dJS_M(4wd< z%{RC$djZ5&_wy9-hm$pFVSm6aDp+pwCvE?g{>9*8P8Hf1a723jB&}(Lkv@ujDvd`-B{ z)zT#Q263(-gxBP^MbVOd)j-3!eCzE?vj90%t8gW3w0ho!eY;|hBpIB<(ijy={BD95 zZ=z2pvy z1GUJO-3K4}vOM+=VI98C2RFksn8*SnH!D5wxI z1qD)A%udm%-vYYdwbJia$oVsd=fCx6Qnl>gA;-~=5P}9Uijvz6-^0$qR!HzH3UUa$ z&5~?D)LSmB>E=<0nO}M6OGOtUzXC9vd)j0bgUMX;LL4|$`JP4LT8UpBIu;dBAA9rhyS=C#YDP=$B`DV|h7x$PFUe79qIO~ZMv$9BTZ_KB#oA{I> z>jmr?%C<*`s5Mzn%b&aBKa5br-9FWL3-{U1ehDUD2GTFln-T_dB1qZYWuJTW}_30>_$<9&Ymx3C|G?iRuG^(cz9Km4hWHg$H?%X<-mHGSZj~U|Vk=PvPjmPP zszM&4eQ^DX9R1Z7@;Sr~?!AhO&K=sO_-j;t>6UmKE|}UB5!_K!2{4j=E-7wbQt`Mt zf9w72ndp#O(@6k*_pA^*IYszdyyn&Y^-4{1L3@p86E`K{dC6RzR_6j! ziDUSlk7QKqA8RFr>UaCISz$zCXKYwnYP>}lm(1;f_WY=JpcMn(42^NES)(jJ&i0R~ zIjk}=G{mYXOeXWbAN?F6aX2Zv463QlW7V2`I4F0j-cyCG>mV9W+btpg0pAA%-sJ^b z2|6o+Q=E)f$(f-cQJGHZXyH}WJNNhHNr4>_Lc@+LD_+l5U!6)oN`8{{O#^Yxa3@@L z7c)p(9;EWQ@%h2^=X+82;WK)1Ay&mk;@MGPqNb}(MX*8#`qJhLUp+9Ux5~TV0@$cg zDx_Xp0QYx?z4&8_w6u<`qzG414L^BT9YNJ6d)>CJcR)VH8i;t5&s^%CV@D&IThggvtL{7Ef*H_nUj zb`O_%^v==kNE{>2y5c`dg^&?nw0l^dZ!wVh_};wP1 zIzuuzjGC%b5ZRH1xWdY=J7LnJL*oMXlIcrPh(buO^Y&Y;GTG_Sv@1B&n?V z@TDczUf|KCcsxkF5uUhlmA`vMn9)9*IlB4NF1vC3?UNr>KCgrN<#P*0{Diw?x&>N= zSw6Ccim|=k1~CVYtI^V23P?a*v%z+WWF}|_T9bE7g%S!IAuraw*6vwJRFu(Qo8lKRR z&$9=oXXGB9j4`rgIXHVjZg_J{9bj5eMGgs&VUF{}slu7P)k2#RKVr0YfM!5op17}i zHaY&8xvp8A0mkX+Ua9{yVJT>o&<1R38CmH6ZXo{VUpmOZinHeteJ9?r8&N0Q;v^n95a&vNS?ck}~+DftN4iX1g@k8!6^y$Me9Ta(DswQ=m1*@Zx{ z*|y42PF8hVT0okuI~#!6UI%%|^}5p0Vx z#ykmkGv3&j#8*&n|gQ$!9=)$f`%tJme9lOv0KU_90a0lWipwg2`+wesC{_~8LEp=Qs$LvKs5!@ z#St)gJ;{YLZ?5EYbLjvC!h*NSF82YqD*sI}%o128lyZfS$VnLx26d&X z=Uh04qI`5*x6IMGCJ<)9L!>2BC8?|;Y+fJ96%LXk{P`8=rc#!Y z*6Ip8v|AD=AuaUOj?7@;;!)=v%^sHS2o0Sl0%Ztj;~*3Z%-+1`0oB~L*<)3RpVIF{ zhgQnc5rSZZVkuoZB3}%=la9Oknm|QW52(Au_QBATYu5+7S#LfJ%X!GWd_Uyl8U$Jh z5#Z^rShoA*kwsky!5^HXL=sXjCwsk1o5NGrQrGH*agZRta9$c(0BxC5!I$4ln2te&!6}252;BCP z*})K+*Zs(6M?x+e0P#c4>cSA#E0NDkmc+7~!3ra!A28u|obgG;3teo7tel+?V-$I7 z7IZu1B#^yVR}r5{fEeqAyl$1GQoxV!gM$66+*c@mbk6@5Fi1XSvyXCN5Q;uS*$NYB zBVg{CAQl(yp|p?-qhDxA2OOWB{k)C>NA5KJ07cCb_H+eVWHUg@&XI7G&@}_E+l5r2 zBG>~EqeBx-wjT-DSp(9_K9|&QAI7M`F=0wMzYejOz|DIiAKyxM0jItA!C}BlZvE)5 zK}V5_+Sw{=gAC?wwrbR^bwi6Ud3}I%oP+(q_U~m+MtQT-D$hYAmh|34IL4^8-(2V5 zVH-fxaS%^*w@G}9Yh`%cd|&D3ENL;JGk~S^g=K>(a@XHu!qO+wz31pDg0&2zAdPYBSoCZgD#!`L=a_- zo0Nb`&JZU8L@x%2uVj@j4Yp+KLCpLL3a{CS&+-AyOy%gtPxU0}DM z{_eZ|R^77VHQBp2FXB?K)C|+@23!{PTZAN>B+=?@7NIdC7j3jhekFb|9NVa^9a9$Z zMEm5UE-69!h6Wx%!F-|<%1ZV^YGfvN$zt$)_6=@-8+9OAzFbpZx=hr(Dt`T)$4Ke& zXaQg5;xoQt9Wt_(=e}G(Q3;I4A2NZp`k{mCYD+9`q&a^7f*^jLy7X~h0WndID4EaZ z?L&E7w){!GUFCS@M`kW%9xRcZ(hy9F*AUsRVwb$vZl-)_%*fDQ8E1;$xTXp*qqkF} z-o5&uCv#Ut#y+!jYRaBoxWGd|AX8z{Un)thK|P~9z1HMhwjY70Pr_-jgRDc=+@iTY z(l8BgrpEmo^-dL=*yfpVxI~0Fym^QE>}Mg4D(Y@uFG=k^v}+GZLrwdI`C<{D!2Rsk zrj=_E&iW)o{i~I(Zxj}dc3dn6-iLY^Q80~|ljTdgg|Bq4=IXdvGnxC{8X}0yvdpc$ z(p?>=*<&?VJt0U=12t7Q%xNat$`J!C!ey|;-)P^Iy@h;De$R~+8VNUto3lX%Jf-EO z_75qx#+f!!`x_Uwo3dZta$4JSXndQYLjKk-J9&i($jri|^~-t+YAasswttNsr@7g5*L|qLh>xfrziRdeTw+d@(o5sXR9)!fWZ2dFqezQoJ8!dgZt+ zex=-8TfFY!RvMN;3tTp<5aUbm9o3|6QORI}{6TfsO2>f~72$)xF_F{nxo)!ja$^Xw ztRgaut|uvBlA_4FZW}&1p%c?mc5a3B4KmLVl2$aftUW zzfQP9)uXH&=g@X02O=Z+)dmcHCLl z#yo!(6>;zTm_}KunV;)AVX9`k4D#=t=N=U>glL2;wI+0vUs*Wlyk3WJWrL@4oAQ3P zb8lrv%(w5#k_4iLb@KvCrSe+yOM~djt1(Np3s{-Ae*w;q^{y>&kjm@m&H<<_)ak}e zCLAb%64J)b^}>bwC)%e$SA?P_Ky6)fli>rOtx6?UK6?W-h33_C-7sf8+?Mgz8Chkb zSeh0TJ4H0>I>I?MLwP!zC>Sd1PZEOq^D{~cfD3r3!T0#xrL}^~zUvSf34?&B^N~cO zUnKOjE@An-0}<^|!r$bpjI533&bE35bLfkpCrL37vpKxQ$1DF7+mCI%Dpm`^JcuvN00TTkON;)KPqec7-Tz|G^n?R`MhFQ)1+q~;C7q) zcIQ1<-QH;4u0p66G~zC{B|yb;@AiG<73bP|5*|*!^in;k>{TXbQatV^wSmKhmv?M+ z4sA+IyQ+4SU-Uj+pmuiw$Uf?ED>-fBH0qQkCvr16KgVheOMnr~>bw2^)7evB^62a> zgcp|qoy7E$%TP#HUA?(yx|QCp?(x1nQRf?~LrT-im_@|*606A>_ux%>LBFT_lDqwf z3kubUWSvoWqC;RKe&j7Q!41&x8=W3!;!Q1_LyA}Ju?Gr0BlHiGX-nF3st<<`SSX)R z?O7Oq&x+sn{_>e})5O&V)7)FGv-s7NZR+u;^Mt2Dk0^ot#eqqc1atk=h{~XzHOYds zwMXUG5&M+l5N`)xreDIy*ksp>7xU(hfJkT^Y~AwYO8^j!t(@ zXEy6r;}F9yR|uhtV92Ux0zr~Cs{T$&XDRQ|$=EmDf~HLkGRxzazq%9J zq(8{(^8_2K7EEq+(cWU`X&$0PPn-9VYxgzI+LS(>1u~=Dh=w42b8+z4&8c>)+H+=> z#gDWDO`IClq<;Tsher7Vsj!-|8b`^iM}<*al3doDB?%g3D#n(D`OD5vhl@1|5@pu< zSDT#cj*>D-iX)u|{zTh775`0#k z1kbf`#clV(r?;FQ*o;qy99Pw`Ht(B;01&Tg7yHjl-p|6N`^tK<-Y4~*-l0!0bg<{o z9~zAjVwH9xQrg#CH$Z7W;QSmTV_$vOiLgCQdT`Cs-0_2^zN^V2TPNMy&#bJ3@l`Y_ z&8#Neb@~maZaIBbUF%i4(tzBTeM4#XPbAGLhx3Z;bxyik;Y=NPuEL#?9^qUY#+2B8 zvXs63Dr9)>AYp96?UjDrTvu0GtT$Yy9QkL1h&YRCroh=95P#%iec%+;VaoLBvg;+$J(-H|CquE88M(&!A%b zT;}n$hVcXURk?%GZExsY5wRMV7-y10fK+ziG)86`>07*VW%upd2DZejC*lN6RmRnH z97QsX;%Y!vj{cEa$~)_9*8}3_#d#+k<%?sooco&6!G@YBXYvu@I8T z`f|5hX`aou|Gn03BAUA@5mpfdX6d`9!L@ib9I2bzk6BnY%EZs>5u|Qg>FAV_h<$lH ztgW9NoVv^7(~l0csSHe_xD$dOZr`2vex9=-UZY5ryDxpaR8d!_*P~OMX~y!N0+WqzM|NzxbUr>_UWOjd)P9fv(t7&{%&6<4YDr7YPxN=aFg1PHYozEt z-u9^Lmb#1JX2DTi!eA=d6wYJ4H-;w{_vSuViXBflprY(?Zs3!+4d>wpGVdhZmx51u z?=~6IPn=C#PVFDPxcu6CkLi`^MOW1c(>wDV_)+DjPa3sf zTr*j;sed{@vHt17TEqxMf(b*?Z@Cc8ceYL6Ae2duc>iAN&f`a(l*&C~)ZG)gWc`NG8YtV%+9eD94)TD(nb7K>fI@Rvx-yfLF ztFz8g_2pU(|H)!QA{ZV`C&!%CKSlq@v*yg7TPVE=JJab!9D@C?ryO9oRW#50_Z@hp zlJPMu+lf#&eOpbj*wIWZUR9USx`4sES!WYMP~An(RE? zr_uP0c%AdQC|~$Dbi{xAz+Gb;oT-DFogr<&P1Fo=Z=*GEMuzcLaLi?=K^aC+}{Fg2pE*lFs4Zw`ohMs)RC zma`P1#ASYe@*l6j{&0e=MX`VCda%Cp&LzLQm%uER0J|(n3~;FMOXN3OdfbL5JJg@B zdUs{^PeuRdM6mz!OeN_;c~4eTr7N7lKMvC9_}9gU>6&`rIxfEp3nU?PmLNPJg_37`Ln^%3XwI z$DgGi!BTSbK9@ibej9<#N}S}vh=mS4_VoNP3habF6yBO%a@3dZ-Jy$;zQIE#%6xWX zAKZQb4#L=ai*BR#W2+tG{d4*-+@qh1JqrC7CF{m3L*CU8-x8r zxb&KSVp&i6^x}ANX~++s;zIFvS9@Lx&_2?kc;JIn$3gywM<f7wyadhwQ2O~c2K-)3&r6f`0Xe@(MU;9k^ zMKU;p{FWcHzaEgy_`{z6=?CeCXnxj_=0qm%-Nbh=yY^80;9p_52nftHarDB`x9&2* zn`C$)3}^)G-d(5G%9YM-7X%9Jw8wW0OgbqSw?2|L2)ZmxLPF_Ia1}XE>vxfu{kS{= zI5<}OG1%GX$x2JR|!WpPsF(bA2b6MA+D29 zV`Fvxg>bsf9E46MKWmhP{xLc9LpK+5Qm+R8GS)H1P{9G=J*G4H^70w6c$HIAWghGD z%?T2|`MM%qJ3~f0A7MqQ_;9j1h`JVzVlqvG%5?S(C*32xsyhaQY1&WL@=aXV2Dy=# z-H>t6_qYcqg(WkscW!9r>$KC~op3UU!{jNR)j3h@zWi-s{*~#UhaVm2{cvN%aN4=i zkx#ONUpn?IcV6p1%=Z8M;jS2b`BTJ)Ti6?aA2u}NLkHFWIBE+6nDWx~ zRDU$m^Of-B6PFL_p_sz|@BnE_*no^%&(EOK{5A|6e@_eZ!~f%)#|U89q30J!(3j1$ z;1@sMQp}EU&3_w%VFZjc@c4}d}^uaWMR<%GHCcr2n%c#M}&|HdiB@=c(uxv zMYSKU(KQ9|Lf886YQj0x;RImcq9}=$px54gMOH4O8#MR<;#`dD+{qPW$jDboy z>VMqnmOz+we85CITH?E2Fz$`cj|Bhgm#N_MFU<<0u#1$3&KUmS-T!gLh>yaGecoR& zgPpVo3}b43{`miJM9}l+*x)7=+@T{ypTBq!4qWmly8rcvHKG{k%|Hk2NG-JC%aIu= zHvi)pdt3qwJlvSCh_>J)Ou6X-|KIA?pSPNU8Rm==ppOlzhj7C$ukwX|PzFDLW5=kT zodrE{iK_{#5HOAq&eB)lDEJ%o@bfw*oq|(EpW5Pw4F<=v!mCd{?>oEW9R2)_9e={O zQNj`HtQ!|bANt?}E1>-ADfa&&xpw~PydV+*>Vyo~yq_D4`+4otal!xczMX#(RfYYT zw=9i8+fFA9zu?@l4A`+O|7FF<%)DW!^x2=j&r=8Xy@1N@+>V*;eACV`!`;KwK;+nZ za*bXBeF*AFq>JNkG42R2{qg>;L1ZA3MUe(#g8Jh4xlj z8J$)KSBD=}?oWf=F%L>GAfAg9?nc*&SrwMv^=Vqpe_Ny-aw%yOT|?o8-7sS^Gea20 z?xST7|5pJ@317~Tw!4EB0M9az06kk6hW+iI-yd=ajwFqv&{_2AvBU6cmD`It=$9Si z`@1Fo@C5cbo=T+vD@%ls08Jrr`;XMsUq1<>g9K>A*|9xn6+b+Jad+1XEla5z53(-T zkAsR3jA-B)&pK|>0KTa-*5e2YwEY`3` z_5@to(lxb)_>;U_o)h`A3sN;%TWp#ZXALKMmqL0;U2TYH1d`d-^37V45mFPF-6?Eq zDf{zzkAZ~_nQC5?;>hp4Q2Nh;@&`-BAq|$~sbgZva@cIt#L*BJtM<l)`0B}?)6 zuQf!|@Fxpx-8=O}-RU1U8RLhP%i|mLJZO&`@?b!9$)tTw9-qACPjDO9rai}764|Kw zxcE6GqiytEID0KH1%&6v-|jNM^d&*UUE>iST_!08EKJjkOlt3LU90>{!E`5{N{VJh z{o@gn{)R5IrrIu)p}?Gl%N%vxl-qPW*>%`b_bA?ySlS%7dBNqA?uhgSdi0J{NAA8r zi$OKJK704));vqqqqWcc=X1;rH$BU8@Oy?s%M`8vXvZT5fkPZ1gKAIC$~W=LNS+LcP3>UtVnpJ$0%3a?`K~@%MZ9-(LGz58lz8 z8Iph%Gz{Q~WpT7kb>8Go*s5KjWS<G=FGZbU# z-lbQBt4h*BZDH7zO229nvB|s5r|2kmNTa`A-19F$RGiSIV?ZYn&dqzi`>1Q6YAH%08|JG3-bCl-6=w>wBiSyqgRh`t zDE9>*_M5`RN^fT%`5&y8cy^FBt}pwr7mFCQvL45rcfqE>xAIkX;`6gL2L~Db6UmAh zH@>MbY(Uc*{eE^8C}m6M67HxE$}mGf_WY2utD!4tMPB!RmvNVn_T(zB!3w87lp~}p z8PDab{jis`)BWV4*9lzK0$16CuHD<2BNnxBo?{RFjg}_6_?;#{B5_e$@{v=zO$BC`G4y?yo9*-dXJy0%Hin+IO(u4Okxtr&U%J+?->9|T-d;nml9Oe3!aB7P) zjlO*!A}@L~O~2S?02PtQ!H~`$#F?T?NM-nN0%wZk_QHcZ$ej39*Z8mR){fIy z;RT0H86P|J781DYxCytM#Mmyxi*qIEvHP|)LTF@4fMm}2`Rb+o z)1oB}z~a+;68?fcrc3ZG>IFQg#tHg5q>VGR_BdQW5_bBhy!T%V5-!mEdbFlk6(X&I z1c)zXOVc=>4L=Xg6cvrrgggw|`s|~B922u9OsJ469h=X`MkMzQf^VPT8eyXYB)L7;jUXbzhpK^=EL>igWw=#IEJk zo`|L%ZEZuS!)@MZi*SZwG&|r$%e<-1o=D#E?W$qcKZ|w^PB`*sso1gFuA&H4Ys5XJ zZRyKaXcn1SQLUj83(+-hRnuDMD}QyIO?+nbMBnJ(Q+&E3NfLmAAhI!2IrJnwLFYu3 zSF@A(mI4kmo2p#W@YOf2wHQmj0YWo+hR-yl z-J4TX?!=ScG<^~o&QvT_vpwgYW7{`5c{z$$D4?;R=fsjn^R|5A)~*-!%2_c*Ez(#+iF-om{Cp<9#AN}XFS?S=fa1MW(-na)KH;}n~_iG!@^mjX_1$I#Uq=yj|` zs)&8dzp(w$Z0Jyq<@kLU*QKBwhj-lZ9U8j&aWE?Y2_QqI<7W@E$_EGdGkJ>aCZ@Y6 zs`)8Kz~t;fx3Px+(W-hi9g1<6Lm9+gy40VQisCb1M2QP1&^+?8*Qp0kXy+n&HQfw} z+11W(K>h6<)Fs^trvHgg+MecH8>{@#!)az=aR&hyGAd7X z8btDsrTDuaS`TMloaz2?~?n)nHAEm&r-@92LH&@lK`3XV2CFum5ZBJ>#0p zy1r3S?4#(Ypdz3$$|wpV(h0$eihvH%OHfogi1ZG2sVV}}Q3OPqbg97t2uPQf06`)p zKnOLIP|n)nF7w>at?)bN(|KR#lNqk$+Iy|N>R#)=rYWAAY+o4g&pCf&p*`H{sz`K; z2;bz-U0_jMJU{5uGTPB>8Ts)l`2}xu|NXY~^a`9yro=1EzWvxaS?QY<)t#B$QD&A- z^_%%hd@W@1?YCp+3Gp!vdGdUrcGF{|KYVBFx?+^s=7xiYYq;-qAL<QI~s!IIy;*$-v)>l5nz0>e|rj<>HM95{x#^5L#`rb$z>CA1!uAczyqZq%b_Ir)v> z*bS%3_#Gj z`ZZEMB1wO^f)WafP?9?EeHKQ0Nh``seNP)LUco|rc{g$~8|N+?jT|V=VxI*E3MJx- zG<@7`ji=rTx?!i;xFc+?&L!@!q~^pGC&-7c3pf54i2*3&)!~zrX45>Krpd3*+%Q|+ zW@@Ku$I3qp6z&N%sCPcfz6R zLB;L%nDx-^!EaA;E^g6K&l}G?&($LV?HnK4uRP#7|BNr}<_T?RXo?}LQ1j^o6I6m* z0?2TWb=slztn;Opz`-_2(9Ggeb)kCOZK76aCddzg^NzL)RaoYwJwc^!)OVt=x;frD~v37fXuu886oF$o7;JLo< zqm1Q~eOX(F6j??ZL)~pnHkU4etYCk{&d2yL{VB=Qh^(4P?sS$?7wN1va@1dD1~T*3 zt&Grw&U=rPPOYm+?hk}bcO8}sGIs-`^jyN>glTiSovG-Jpk7eM6oS58+b+BLK1K{V zaL=#-Xur9kJ1GIl+w3-CrsRbjOEGC5IU?QmC(k$Xc?E?KUDWa^4<`bA4e&$S7p9s% z)<)Y!Hd}{=M_0Qmq?yPE9r7h<&)l=OEEkS(;?ME#ai>Fj1~<=aubg}s^txPe?o*CD z$dyuE1(P(34R^e52OyoRFfQ=n)M!sB!lyxr07@ngfIxJ@)GYz7xbQ$0>ZRy2#ox>P zqt#M$Q-RVq_${%}^-}vaqmzd>3;=wFp&9z!0GClF6Mn4fAPK=`*;wksxsZnZF8ohnA^tA0NoAd&ai?$ZqI_!WKvSC95~gdh#bf1fGAq zUcKHh$WnaKD2{dKSzv>Qr`c=7zM5g=@zfiy%)n(A+gg4%n&;3F8_-p4Rb&6+Wi;>l z$J}TuK2$B-^$*<;nVbQ~iaX|QPM;W6Ik^&>+Qg)0haz3MCg$jJF?QJYDupLYh zo5S0GuOi)Gg!;6IY@GkBCO;87N^!L8Zu&<__2_Toi>`8)6lF`T?P0Q zwk_+LV>mj7?zWFUZ2XbU_*X1cqX+ETpnCHo z(|GuTu@$ga<&O&2Bv}*1J`okC&cE6{)|Ul#^Y?0Ld%Fvhj7a@C`S}BRN%B^2Gvrca zVywJ44nOSf%9bxRG9Y3$dav+hoT9Wg7({IH(v1k^n&6R^t~*F5rgm3Ud-g;+zP4{} z#fOt0`muk&8>!HE+@@ZsAH#2I#eBbmdwAG(XHZ+H>U`n14@xN+BX%^`6=aurJDUUc z3J~P(5W{aLbMo z+a11jnbPs049rXqC%K)Z9Y9qZ@snPip?pztWvmx5Ov37FkvmKAN5v@#aO;|(S^7K; zHO=Y+xQ-xK_HTwTAJ4)MaK=)tlipduV2)ydqEnInqWT@RVLs==cOABP1T!&tiAwML zf`ttN2TgL)ua!NmJ4n>Yv-Od2SvRkaW-og|llHzmk)*q`08NwOoS5MTW8XiqxenbK zum@4|!q2-DW4YhnwtZCg|MG-OMd>8=t>U!yQ79ewoj0pp=)URP^mf7wu0J3Xr$g8( zrbF+tzf$L4T$&bXw2yk6_e@X((XgYYw>`lwE7umUa6h1pC>e#Z#q;XZ<|QQZdb+x| z<+|OXKR7?Z8)9QB4;?;#yqjfGu2E(@zBZHZY0RjXjB0}@cDT?g z*>~%RBE+P%`5)-sJ)y*1J7}2Ek%88Piog=TD(O8Tx*E^9*tQ?t3l8SC7FVq~`?>fB zouE#PD|oqXSwyTLpxMb}1Tj-aL1;^_0$vc)W1>a?s3QDcY*QD;1X}c#O^Fo_`vmBw z1JNK+O9qgN&k+*e?r!M>v?2}4lt{SY)J({ri9?b>b;K|r={-|iYZ&zB5@dG+l3l%( zV%jMD>P469w+)h3Wq36V)+Q+B_pA>(Lt?p;rVI&dzeqRg#}-!zq{wXs+Pey->4NRt zf{G6NW3i+5`6DCw>Lca1w;#LZ)$E#bQoc!Rbw>R?UKvM4(_Cs*3ua=LE;n3_ot13A zStNC}m56;D9y<29z_OpMx)OT#;tM9+$Z;{`t@#m?Lpb@;!*-&*1d%|ol#;NldsYUg zbF=HTfK~wTYp@G&+xFG@xeVxA4j1z;pNUzYWLvkc-sto|#&~~|VBMQ~BQ&%V4G$Iq zmwMoxe2_qDg+SgZ%`(T&kM{`a6}j63et z{90PL8EFRS{!Ldto0lQ-z*cFNo}zyzxh+kZt({)+ZoWJ6nLrak5vZCX`hbL+$ZaYH zn3m_MY&(zrx&ERbbhKt(e-7w--rN{Tc0t{+w$Z|g0>R|M=|0nWIAPvwZtsTJmi;Bp zKpnIL8TE?SX}N%3L9RKec6ScwilAjnAvlc4lmHX+mwJBU787wertd7tdy^X58bMzF zl}Y{?2}dB%4-Y!OlX;JKndvm^`nc2C^(VYf%8V8N)n zS6V0z>ADXi!>!I|xqV)Z-=sBgOn~V2LPFg|-|B7dcvjCPzT&FYh3VFgDlF6uPGg>I z$5I})*?b%v*0j1f6IV&Y4pyj%u6~<$roQv^aI_#dPl|w+rlTA|V&-c~$qgbkBs^4z z5qriPjC+t$%XINp?RXQ_e3RHPJePhPZvU?08Cm}%9QU$ z!$>&)!&B8M&nr-vSgyKOP}CU(Kd7a=+h{@)HPNqC$Ebr zdQb}5=iWD8iOdeD!b;BBSypdQyHV6zQCuxOiYkLi3ozKz>%Zl==|-^D{|AG=`b)Jw+| zlUygromc2qpqM*f&(Atq_qX#(6;kDTiiPL%;|3zm@A{5`(6JhY+X$a%Ulm+!NeBQ` zPcI4YMro}O#P8yn`YhLJfMsYfSSl%pl8y=+sf_#FOt-)xym)bcyP-P=2N5$dbuPu>p#m7;*f~aR=arV~g7)F}%|`RtK~)9fUBS;AooSt? z1xq`gXx&I~;vl*jO@E*4n&Pq0ec|LlnLAHKoY|EExM=n;bu%<+zm7GvDFru>TFTv0 zUUT5?ENJCZ%F4>aw@d*Mb{N5C)}3zwUmQRb0B7x`{dSby`pAZrhERozO?pUn1|To} zp!7E2Lp`MgcoSy_fOt4>0QnH3-q1qvjO;kHgl_{ekwdANgSwsw^@UT5a%!{+@QJr0 z#G3fX=rcZ^+4)_EHEx1Ip0n!~fh+ETCqANtKi9j*y>+w%-G6@aZ|#@=J-xr?SO~Bt zTBX&V$(oahHDL{4%p2_pwAam}ul=urHg41;a>OZmV`n-{QuV4lx25IT5|3yVJB~Gr zC5=oKS9%OOS>#G?6sMD8`T?}W&TR1GIo$lYvEH_9YuX2gbaF^a*k$(V!#WqFbaFp= zl)CKAav-x@kJIA$;%0QFb+S!(Z$ZjVEne0P|NaePt(*8F?5{!vq+!w*aAozG&}M*} z`*NT?qi+l_BmH&w^M*)wpeMH!(xDs(le>XaGz`ih+y1~N!B>Pbkz%Z%i zQqlZh=iZY%niS`XEd`F_!}>RIqr$po7WF%lG-lH8m;l~cH4RY2QQ)frd#dr36e!t=U+xHgyJC!-L4tHm~%#WCMY#phcUWNMJV5OBrXI4PH{G1&F~UL zNI;!W&t>$2Nj;JiQr>xkpTpiXY1Bj3t=|56Cx)ol-~OowRzlanxT z{&!wE-$QwU8(A~d_FCTl!IAryTG(W`30%2V2QscO%g1}r#fNqRSB-$GSkg<3-sgwS z*Ct>0w(WZ3O1amAE;>@}zs+K*@O#dYIZG@C3l*c z%t`>7^T1S67UAGu@A5RY`bq(@cW+W62Cl-977ooF0jQNvK&;3lfryf)Ct8fE8b@pa z|LR(s6v7$H37uZ_if_$#aJ8fiR*LLm-a#gU?7h!Zg=?@RSN+V!hb+{RH#cSEAURN- zyLc(X|E|^IDCdpRsjtsCDajYrw#QrduPZ>`b$3h_uiyF%m#hk`%-fCsAKcddx}p8s zJ=FhoH?(jk{?XJ7#{+lbJw22@&>Cu`IzMay`KJ(X;AAJ{*Aw6UsS<| z54y9krY5DNv1k8$`HwuL@8>`rC^Z~oN5Ay?9sH8VOrNmQ!_$J*N$>Eh_<3ubqFF5K zn%wH*ec+N-r}pdDt;jte>#dDeCXS4hY*J6VcCHoj5w%cxWe@mYt=sP`)G_`j55_cj zQTt&BCNF=JWL}|sEyz7l~L!`**q(uSq7Gx93!Hc7Cp(vp8&*NgDw;tF5Sg zBUQh&>gXpWLr3)4I!=UR}9;ZD*M0->-E;V517?toB6Wc=`GircG&U5nGdROlDgJTb{ha0%iN(B2L= zR5ZoGvw(iyO=I|&~NA7J`iGZwZEKr=&&g5rxh80M1^!{!+5UlpeeGl)! zqmNMv9(Ea;nTfLCkc`)SVk`1g@L!dL$9*`(1ipMkiHgDD9C(Ikw#}>oXoPf*&uXHX=YaeSo8irY@ z(L6f;Za0Vhs>Q2mtx<&W;F9BJw6tR{QH`dG8(f8w=R#97rfv({?0Z}KjjtqmHIGh! z44_9!L^yN@CsN^drWAF+0pd&IdE7Bgp5Z?pgqN+IK~ucv$Sbr-L- z%Yi1LDxGs19wOEpL?sf&RMUOb{t&e~*T0pm#*OeBWV0LPJhjaYyiGujX>+p-D0;(a zk_O+gtc1wx_tEZ3FKCnsxZU#TeR<0U@g2W0OVEFImH!nHz-QYjCP+tAA&9pcE(NYD zi%Av*qNt{_f%N^n!di61QW<+_J}f8Cd_9F{KdkvI$x|9q_aVK0ieIye-d_2b*3byO zN;*WY1}SuSetOh)PXM2D1XEd<4x9lLho$J)K`~{?C%Hi%BPA?*dYqCkC^H?#$-&nT zWobUEJ{5h7zWS+Asw7a#$BX5poa(E#EYY-^-##E+@+DZ9kNuGPCItlrGnab|t3PW% ztMwAIEl_MFbnWxwUMTn6C}(tbv30r2Vqh&z`VC`D!Wp9?r5op8@Gknj1*v+y76c~b z&pV1}_p$}(r%bxWn0-`>5Cny~`uTk(4omx0MuT{8D!+JtsEyQ8X?$cyJK7veJpJP(e55hAeRO<>%r$YuBc z-o5veMR=&fvXf+YF@@VB3(R)*>578IX~q1>&!}K+&cyUCdj5YjGcBf_;R~-%!b&9% zg$SSy2U#j|7!(hW-Ca0;Kb1K|u}oApyk4bdHQMxRE%>S2!{NS5Y?g>p28v1DYmjG# z{FmSZXH4DSk(z$C2oD?3a=K!Cc1#=Op@KyIX)&{9ZqZePW=0Xu$H4X?=Bs(pI!@F| zEkULbiJ2X`Ghge@qUWR50q0a?oBsF-cmMt;V^qz0-z%Eg2y>BvPAiTVvxI75rV7{x za>XB?bQqEQb2#i_@Vv1sTGJ9ZZ5Ra4=S@m8>%DzY=UK0C(d1I)3ZB;){KhmXYcjxF z%u~=dM_s6Y-`fw?A&W4GtZ-LXFpY2(6e|y2(4j5$%d?;jnsAk4Oc*C)RDW>a^9BDB z_xzd#j^xfiZwoM~H;WXg1$8WJDXWHO!cjlYjyLU0k8T4Lptc=}5xuxn1?rC!s8G%$ z=F1WRR?4YCplWgJ&D>ek|Ek_YVe}7xvHp`59<3n7J+aSLF`sXM>bvCoxuQ#DbRIgA zTAUcB0+mExzO$FIcL{7p`#gxy)Q+1fFcs(=h}Ec?GVk9(t$spzStod&7~P}6RG{|2 zxciaIm;K;O{pasoMBaSKw}tbVp#Z1EOm}dpM-25NjOtz?Gqxx@3O-Xm!WR3jzn%wQt&d=?JU5u>6KCNk=l-_X-6jsU*z}vgrgrv)*E1bme!| zGaM_nu0MW4;hF5YmHV#WSabZ8z#VNymS zZFlAXWnZxD@=0`ti|m0}rOGB!=wkQ>oBO*`lHCUUJb0eK)KnfjV57o%(o5t|(OKY+ zoTfbyJ@0V?UL0z9jESGQ1ig13{2t7+^91IFSO#)}*5#dBqAb*Cz@n=HOFke@N1?K8 zm)B24mMFq{4)A5k_`9FZ+_zNafj}C#>~k01#bSnE0*M#c@F(av4v|)- z3HFcx!u7D$FIC^I0C$Po-ouR9ugDH^U~Y2vT0_R> zB}gFiw`DKEH(!5?U>?#h5R+o~o_8~UW^whg9r981qV=XsaFMsD>Y{jhXZTXI4m{(6 z5Hqxj6Bmke_ksM!-%|epfa3q!j3x+#c>yasQ^&bL_F&LzJaMUSMlJSY7RINL$ZvlF zTX^VcwrFNz0=;{dO0GC~mw3N<6MDYpF&wRvkMA#05Q}6% z9#;Q#mWXsWOjH4bY$?XSMCFr=R z7*Ln^WY&Vv^mNff;IQ0fQ>~?Ho|UlBb!S5sG>Hb#F8!MHQpqI_tH7d@RZDUab)z_7(FK3{pI)%6iylrr zBY0juT9ld3`wf(s(?gX^zD2*baQ?oc^n*p*LYdv! zI1r7%VJ$(AmFSafBz$0KV@#I%W|XO|4Bhzz>Gd-J`h$6Sm3Z*)`}&D+F!8fw>lU&W zU%(Pa>?1FgTqVdDRpk;z(7TQyw4qI}uKeU(fB(}FbZ_jjwN8|Iw7B4dZENLH0Y#F5 zt#+A58<_}O1rTTro(?{=fV{&b=TG-8kFp;-GasQB>pcY0olJa#Sv(!jJbzIr=x~w3 zFy%+~_Zm9yKa}C$x5hMi|9MYk>Jqnn@i;7W`P2Q(edxik5c;7V)l2;D5oC-k8{3l6^HF=? z!~NYGmMVxI;1jaFdYr|)uRuAyY_hrP5~*d4y4Di{QU%cSz4w6Og5}qq{F@a&JtXQ- z#Y3-qt-v(gCy{@ARfW2c0a^S^kAueOCsGz1*{AMV0ED;1HE)G)dhHx!lC~%ej+WJJ zBWCJ(@nw5>fSbmaUzEjc()EJiUpFzOc8N@?LG7M}DqkF#Oj3pyhaY@Uy!cL;%Zfq} zH;wXoEa+1Wg1V4Vt0pY<%?N^NH1-TLrM4OLwBPIItfguml(O9R_}GF^m<}4>pv-=$ zu>fS9I#y;ek>J%KbxptO;=naWm zr&GmQDofn{Wt4byf5pUe+w>g5HjI49Qc35n4DSlF$u>dnGDI2UJ!e1u=gxk>e7)Up z%vKzDWrm)Ym4Xk{ccDv7Cg`Blq4D)ZCSaZ;N*;S1)mZAqKp>d7f@8*8(D^Rf1f+YQ zuHv-R)Ts+-k7-*+rYw2<5k-~zujc!|sZ)d#@$$YClPyP3>jf_Xv+xg(7d!Qaf#IGeFKYD`dGm806dLB!8v-+@xde&o1C7y?UB7^c@&}6m_IfxzbY_)Rbc+`bo^%p=CN%xbENrMl7vCyqU`|# z2Zv5#$4=(S{IiWx9WG$$f8{7JVOdUYX->N?pB1AJD%wB@(X%})8oo$9iQWd5<5Us% z{DpRz^-xEmyF2*>^ZI&nxy=f~?Us-8X3cwk>|-OZJ9qc)*KPL>s;@wgd81-$({0(f z8`FQL?C_ryO-Z7NZ%lYtRTtZF<^ zlMNF!9BnO$2QNRfR3(=_ zkE;XZU+;m+~9pHKdZN!Y#SOZF)YF~71 z-*T7rhNb46c3a$hG4$pEC5HzVZVV#dw*h;x!=H2pg&S!uYp(_M1J)1w@SKqjTGV+A>!klC-m<#016ir{o{iYSMM0ifG_wcst!!Y&^S~%le`uU{}}iat}W& zlM)+e-D`?)rCycF&{HV@pO|p$GoWop2;>c?zRHo79GiAEhl?1Pb%~6??^bH$~*6)%6zHYOzBulwX3MsH*Ti^Aq@(k z|JP06=Vu2P=6TdW-I1q3ulQt!ANfz1cXMpNDl3I;aB%gx;rKNe51gbDv*R!T&Y^OI zh1w$R!gixaYRiI%{MY;JfAP>`aP1mnyOjN^P(tY;1f`pH@5&uy8Ixo`B|szVycV;$ zsu1RS)W>0GDFaGCt}a102T7P@!DrU`h3^PVd|`cA4F`T}WLG~R+$)BPSqNa;yBHZl zOddWPGR$w>UOz2|@0{7JUWo9uENzSPp7SOz4_DQA{_g^yQErJy3~r3EG%jM$Isjnes)RUoq!%nT!mlKNj;ck`f(-0qjd~##Uft#A9WLGnf!qpiS z9%KzEfmJbHW-sRxZ`!4{CC=6EUtZm{`&Oz&tK1sNNPai9UFqj#rD*s@Z6R070q4R= z??RK685MjurS+C_vJ3@)%DvXx>8v8{N#(mU_Wj0Lmj3al>kU)XF1r2jD)}E73n)fg zW|ud21FG4X#aU9?4F_4MNE|3^^FwU)ceux*#tio@BjQe3DeEs^LH05+L8 zW3*QeD+#zU=KgK-6K?Z%(_ai^{J8;2F*e#y#&Ja2yz|rGnyQkX^}0j1GhmKbcsmZD z(I}uU&pX!nM?Bm6X9P~lcHk_6;Q#AxBz`oU_G-mO@!c4Ds$b>YKxUJ!LwZ>c%-irc z&!xm7362E=6I1OnXw@Fra|*y-q&cd2t}$7PNeMj*Jh z7DqbZU|YlFt=Kr3@p#I8PV=)I+Bc7jmH^Cnpq<9}=tza25*o~4n>$v<7a3*_U>IXO z^TRw8Ez-2=4Vb&II>tbnyo2%{@SCrNp-EYkzJwG-#$cX>WBX`?n1gQqqXHev;%x`K zBj#s%IB=EuezP1YGk3e~RW}}$JDWRMxa*XFuQ1hB^J0$le1_}rq3MzXUpKF+PPuwE z2VjT$wChW%Ba^n(2!viBT6v3<~tuBiOjRc z;oZp4M>ZuaBONQXR+!|UL88Z zrQh9TF;BNpTHb}5?Nh5q;}uMO?Qy#p2b3JnPnSi`l;sl@Bhi?FTo|;&S3TmoS=Dd% zI6w@3Bd}1n^Ru1kA(x!G$j=t z2K!2MKeqcl#g&u8KonddqfFe9T}vB-Bz zl9KqhyIc44uJI_1Z=Ro{%|~>O^{o-$P^zn1L9jewH{&p96&bp+P+w{DE>Wi3L3LHL=j zt;gwroQmn^R2+?n;&OVl<%5#+@TakNr5FJ!I7`7+UvdDsbKvrDBqJv>wE5JgncV*5 ziVsbjKM3Gx_N7vFTz0KbbOELKI^UxpQV>4qWJTAOv{Cxz-vu6cRJf2`BxJ)T{IV>; z>5_1J<`TG~y|`#xal<@KUSeh!&5NoAVD?QrT`J!9+p{+rvkWw}2Q{f_Yl+^Zq%;7+ zSp7(D(@tSpQ>N1U&X#QlR%d8bW{oUX%9zW$+fWG1f#glB76NJ?77DkRI z8c>g!f8p%kkp9x>?gujKkQ}D(Qp>r{V#Vy%Tk`8@NR`i)r_7umZur75y7K+)fz|PG z8!m4Aqk5g4Qa@*PY-M=lDNK@5j!VXYRe>Nn91NA*43_>jb@D=78 zUH5$4QK3su8=EY}$`BQ}m+2lhbuQZ%bnP2K{N6OUM|8#62=MG%b3l;)NuhNV@SvB6|d`YT+~8VNbOSx0`V@ogDSJ z`EgvFIAuyD#Ze`7>bnfK!BHgr9GR!}Q+(&<$9`MVdA~?e%asOw{nL~rx}GJTV|~x` zkg^QIZ5kEh0#dGvnfZbR((Iv**i^1F;ZVZ+J{~dt*5~}C(;&S5MTN=XRWE?%DVdFH zv>sTwCc#KU;`hj6k*?}k7vDWm;SV0iQSlbl?3oZJn!p#z)c-+nu&D28|^3A_qvSXHrwQ;FwD0+ z8%BbR@>P3@0g`x6y`0R*lS5x;M}qLuPTRG&P$cR9;;U7!rIpgBV+TbPh-9{N^9j zbg9e9(yXf>h`~V&ByGd9VWJ9N%UadmtevQ6zT-}RnPBL=h-=rIP_%vd7yV{^oSR!C zGBBcWe^301(;vJl>jd_rIo>8rkLv{qMEejI_&8DpUiB}@Uwe@mp%^JS5fo`7f~3h3 zv9!12Fd`!%!mUry|uj%|`~;D%qc~ePb{Ey7S5E z`2Mh{0?i=?xRde_q_~A~&vdMgJMtxEX6rCgER?Z&rD|@Amb880fPrpx@6+h;NcF8r z3AYG0_K!7Pk8g!<$*73CqPA8vs7YPB-k60tqCMsI$77mVQuT8_nsPfMqfmu@^t(I# z=Mbfz0)WVwXhp7rE6hYG%E^)s(wVw}dX0fdj%HLi5@$rETyIU7dljd96Di z@u_kTNAt`Y=1%t|)UV|WdmJ$u)^mYs_i=;RD>j$jlX+nSyWTg*3*`J!0HX^PkoNYJ zrNdx6afv;W%ZW`mHy3u%LI_~%5N+ZNF#Q^oSN@72Uq<8HrsF7$S{9Xx3GINJ|J`AD z|MF+UZ2m|_jH)pcUv$B9^mP!-ANnvBwHothSDY(HsW-#9^?~&FJx15B?{ngMF}TJq zrF$4fefR9b-RWDvbr=)IjtY0hTqBXKhsCc;@ABM3x1U1#%8ZzG7&M565y@pj;hzfa zNvHJ?Ovt;{XRpF@hKr08O}c#0)uDIx2W`ULZ6$iOf77BJ9cJTxcBipeW)%9?7|%tT z5_`IAO51r2adb@+UzybzL0nfORJ`^_WEX%++5g7yw?z)|?jiT0n&s6eiPb9tZZSLA z7TUV3I~>{;=8X(|?_Z-XSK~;qnd%CPg9#6&K{st!6L|Gp#%kr_;-tF{v^=W9&XKVZ zE`FACqu6=j*-Fxk0(-NsI~_&2V|{9PNldqpU+{&|Cw|UrnFJ&k6X zH?A`zK{kQHMYET41eoiPb`XkWk=F0CNH)u1XZd;s>a$z2*LwAT4WiHEbo9l6_0~b8%G3dW%N|tHX+QnPKn${W0F`h#RMN>?H$uE3- z*TCH8LL^xSvK^c>afQuEoi2X+JI%2v?}lS5ETzS$5sf%736Clun&-u!@B-7h+3$1E z6PGiOk11})Pj!c;*MB14?e5%mW#Fx^>*m{7TK;GqOjY?l*2#f?*PK}A!s^94#C4_9 zNUb(!yJ-ab*$DRCzK<;vMd)uGM!Umf|9p_|MdsiPyi-1v*Xf)P9)(GAOSO>Ebv{F! zRMs_VkCj%ntgOFq<6cHToN%kIevL*0j*pdH1rt|%x70>uTCTrl z*@TOq3(n06Z!QdvN8zAvhAUaE4e}f_GL!GwV$t|NO0A!(wdXP_QlQjhA8Lin!w$|4 zJ-|w@XP4WaXJ2eo-=uA&;OTBPbEm^wxa!YBMH<*J<-5VW&Aa#v@SWRInkln7c5MOe z;BXoor;z=yGT}ErtZfmm?R6qCbUo|e=+7~IyFxfoQ)MKCeLGzYw)5Og=@Q?!_N+$w zIw<0=M*}?lln16(@Jz~1PdDKUy-Hz1W~2bpIgqK5FwyE^rS`sq$nkoA3;4C^mRGCR zWXo-`hao`cQ=HoR|4Phpo`s-9WjbYkIwb=jNe>;t$@t{Ax)LU?Mu~sGcWts6b{P|V z5K_U?Z|Lv0Wn%M;uglhyt9m)RY^#V}`lsgKmFs_}diHA^j^d(LI6X3`#U?)&OkVSp zqvxP+q{t*5UvA=CSbUR_;o#|1RT}?$jc-=5yR)-kvINdf8uz`StHUCwNi}A_gRGQd z{Q|z;PaH{)*6^@)mM=?{f`;Atx=j6AlM_V$nTlbP-fZ!Znf zvM3NKpv~WIooKhi+3uWpznUj(@7*1H`otw9Z-2oLt;fGrF3N=vzQlK#18Y8+=O8~n zzeddrq%@RB0NkH0v3IL07@srsW!tRI7)syn`i4f(#)wZzDvr#3nE?#c`%>R4^fsp&)m?1bhXVRGX06^u_9XIEg45F ztsiz+2)zzt`)lK&ppWGac^Z*jbG7D;JAo7LzpuH}qh^_(xtvfN*QY%-*)?P%El6|F z3>}fKCxFgUTK~SMKX15%bCh_`#a3upTd_!zs(V9Y9@v+}1b4de?RL~)_mixKY$WUS z&fSCcxr~fPnOWN;)UT)mJz|6B_r)gaV;~j4~UOX!&t_1 zt6@ISGYw_-L#{+(dtkWq>>ITLgo@f_)^+qSolUbqhz9b>kr# zO5eZvzD(ci=sGK~-8zcTl6Thl*2nAPP^uzbZwwS+S}O0Z9p46E@WfTZt-rQ^qO@5) zwRJsxb9$wq{c-lz!j9YPVQe7pCs&ApW00-afoxZ>l{chZ7;*lJk_Rw@mVOm+#4cgQ zt$w?2-p%3tV=li3V-X~(!u{;yr}XKq;Kzunl&CAsOLu5T#EIVsaJNm&lRo1hI5pAP zJe59~2*=vC%V7lbDev8zRT#XInyUt}Y%RZe}l}Z1`gg_Voz?*`EvfYsg`1-(yBFkJWPPMR`TzsmfGYWGb zJHZ`P5~82vnXVbQJ9N-#y%){7N2-PLjZ@V0bzRJ@&?9q=*@Xe&J9UdCKXh+i?kf^* zS+av7=lWglV6{ln6>l4utf`<_}N@>8}t{MP>`q zD~Z>(%#v`$HsNk_QyQe1wvTW|$E5J1Qd3PjG8O%mJz6IC)cc(W+G||_(l^hWhwWDV z%=J{Wu)lcbH=l4lEjy9z+Mhj=lIPs*#1^@oFIi)Bur8mhjwgty<>?KFRpIkOyFZuXbL|s{Lec(Bl;3Q|wVG!Y=ipy$-A-5|5wL*TAc zP{IA{)ne4rw8ovC*xZLEVP9N+H!E308NRgmPdWzhg6~{M~3sgaGz$pwx{Q(T>tWqBi$A3ejDmt-}@LPw#)xp!=8i$HrmI_v> z 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
xGMiaa@%#oXVi)0>33@kVoT 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≦qvRF#zBh>?$pAzWr(4&B*T*Dg>b1kKf@&M~ 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⪼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%0A6~nMO~{B#!9)9}xLg-9$E*t@ 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%0DTRy%a<>I43eLc_tZUBwXO6Q-yR}z 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 A9)+MN#{tKCV= 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

c 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

)B&P5Nj42vXY!*@R#Qoe^I^iMb#kmrnO9$>fRI zesT&f1WUQ$!#~-P`x#G+Zg#kv6Mc zwl9(TTl%|Ed^KJ=Hs_ay9|m5~r(qos&VU<=Z{=C15{@;9E>I)4`0fkX_pQzSSHh7E zk(RaQold!0FE@m)5^o&RwxrK#*-oE?qQ7g* z!fwGG6XjgQCP2Ku-vYGOj6Wvr0F2_`mE4f3Dj&xjT>XmXImdyjG$UBq@K$i+nA0x^h;0+CXaPBNV(uF9 z5>5E}oZF+#qd`l3+?QY#Xr97eG6xuuh0Jm)Pv01InsTjZ6z$aDo-FCr(2iY+ z&UFJUFf>(R{WbB9bHK}F_!yV|4=kh`jv$x#< zdyiGBdfj-$(;RjcH`EyIb#d5lmeKMI6X!B0>Mk9HPYF3d<6bKi9nEuEl#Nsigu}G; z6HwOHP?H}CPL{!v40{D6GEkPo&)ot#*zzIh zT81aZy`(zq)>RJk()Op08! zgR&v7t$WtO9>=KG^>%p@u3k3yMP2SLflQ0wie}@^G(|QNI6`eEbM+1D!?2f||MCKG z$kXNmbDYi+?ibYVuKnCy#lu!NAhjbh;MB-8PlcnZmm|Gz`G^-+>5?*?9r#0+_#Auu zxH|-r7G~kY6QF?}a@>KAw1QE0^7R$X>^7eL>IOP4NB!Po^^e2?gf^^>M$CF*lki$5$$fvjmvR7s$Fe_xEG9R^s#k1$x2Qbs+bv?RW24Ln0F?RQt*^RTbCCOVHh6hHu~;ZSoNlGPX&-uDI7aV;X?ZKcpS7Z3W3=rYd%_g*^J zr4O{L?4A@HgMv_BgBHUoe$jq7AS`NrSnnQl%LmWkHg}(!LydnpP+we(-nl2s++tS- zpV;+tPq?f*!RZ8JB{Jdd+Szi(@-=I0-LR0kxLC=>&2p_s7lKxRm0zxSegrs6C7qaa zn?gXGHky;8-yCed&7|agZsQIE)_f$#H{1dH?}SufB>w87P+@4fe6<`B**bHzStqL7 zsg6sThH}^c@)V71-A~A|2R@{1pz(Cz(Ki7*(eQgaqAALAX=-z<%;wLm(WA|**V{&K zM1bMvuFdc7Qq#V~GLFyu{eWO>8>n^%1+EY2C1b{m{}moMj+Nmq{5z=ZLRQM--W0ew z`fHG(8a@{w!i^?elqW_k!y}Zm@k~s@OTZy?E$VSa4fksXFrb`Y{cIw z52IXiPSW6`y64^MAu~d};j&k)pQn;oH~*b7qCU*R{utC}ZdV#`tQ3rRO=mO0ETj~` zgNHW)vm3bLCX>{1F{UufJQAU+PXIP6IrhyZLl*iPG@UbF%jcYd|M21pM|t%1CA zB+>_LiIBq+o}jjIFPpYNDZcPFf1ng)HVsiS#qlX+;SU)qdr{xQs=E;y%iZfW!G8&g zSbLk<=EG8t9NzR}4DfkziiYQnM~!BN1Ir;yHQgLcZ~7UI%aN#Cxa8L~PXdMOg(Ndy z_2VA!F_Gg-ZpA2P#w!S^Xu^}KYW7Ex>t2;LRw}@rbCCQPYFf&8XLgtuSVD`irz4M0 zFOAk^BJ@QAiO!}Ck`iN)^5c{To^elqkx7V%rQ+BN{PRTn#-g9aKt2Tp-g5o~a}z2!BFW)YfE@pSM4_7-J`#w3(&-`M3Hw9 z27joV4z3bQBy#7Jli(=)lHW1E%sh4meB?BpovCIKP6oFIUqtbW7m<9+{(p#tWB7ux zgDI6=FJyl-*k+ByB0+g{ACyO0U+j0HZTw$XPq_JU$cRL1Pk+W;T)mLu?=b?Ycpq9d z)=n*XJh}~^A%>P4c;f@$A_;?sl}}&Mn3ogN$>`1OAONtIdAQSqp>yXVxfinBQx*2i$SgtX4QwvX z80q-?Cky#{U#E`e_?90Zc9!p>x#cuGNM0@(t*RUS*|lr2tJh(!DX?iSuk+1gDS{KM zkH2xUtOwUv**I+p{HF3exT9dG0h>;|)Y&yZK=t#!An2gF5Z7LWD1dnoBhEPFT0i zzM@j``CM?}Pbsu5-muHOZvPA=NFPbM6+R&wc~iEH+XzJt48;cwZ6)#+0#&&@S<{_5 zQ|K~7xpbf0O%7LuKj@@sAjEijC(ZNTK(IwAFx^i1ym$q8lBC&7f7G-LPM5SCq>*DM zt*gbBIvUFkG35a$p2eNC3tZtes>CT8)g`fnV4l1z0_QwnpA7ZEAfX_5%XId@ayK($ zI(WaR+|Qb3<`&TVYyGQdhw#JudB+DC(fqRdPFi6}F(scc%+NN>nQYBBJcZUZm|!h-A!r_)+x^FhUl!}8+QQBU0Q;W{Iv&7;$}GBmaoV5xQ5|9H ztkls)7hT;FWcNl`hY&JYby=Z7rKRE_OrwjOsS*NnTXZ>pci`+7UvV4%CaiLxu1L8- zO0$%Z-MJz!9__YI#BP~as<1h&Wn+Xxw}BhX9e^_F0JZ%O5z+Rc1m`*7 zGXIHzE0ACt*bcUS!6iK~FnKvzTHjd!Ou5U$_mTV#H_f)90hEgz`CbhaM-F6{e7AxXykce)7;!RcJf2h;jy#dHob92*mXgI5M2lN-BF_ z@Ek_wc}^j8cEnKz7S-h{|FKNwm6CzL0tYeYq2w52K!1trMkp7;)})5OLag|L@NlxZ z3mJzM_G9dhdCuHGu6zgFxY6GtK`$Zv88x)=XNv4q)eY3PxdVVO=@=!^qLlOM9&Aj~ zaH5m57r_B$qP=e|6E43TE#~ieigBiEZ%Uy#H1|oy_52CDA!KL1@&{_*#e&CvPKWxxYMXCI0&M$GWawgYme-HNL= zN%Bv)5V{oHm%!bN{JBNKX<7~8Hw6><8d`%Fk1j5sn}BQr{@JMl{_cR;CpH@9vCen^ z)1o|krpHlzglf0^kh~;N5z*G_vGi@0Z~YmNC21f_>V2^nMa%DuzPrdjqj7a`L5ius z6W%;THU>`(Fq?K8_Pxq84XZ8DefPK8+cYas#i#C??)F#Ek~-L)a1u*BVq-w8k4?hJ{%`y6XfG_kXJFCbKS)v zb`PZ4A+%2_3Q#5wH7<}s#2%ulB23DC#d2&Pez0+M1_H?&DSQf9;NEvls`YO2;6|{Y zhFHjZFVP7&cYKY+cI$-JWA=W4dMe@2Pw6D_d@jrHZ3&@CQ7OWTX@P;)2X)0iMwRf> zRd2g+=jkhvPvw@ig)djj<76`>oNwf!H?u3asyV!no-)g(;RxpmOOpFdFV4(>5-T!B z_<2_UmyIQ*h;qm^OC?uW+JjS$GM=eh_1CS+VlrhXmlQ0?=lL@IGGfV3^_N!= zkvQ3AD|XMbBgym2d$%-Qf_pDgZZ7FuyL^;K&(Mx5zJjbPj@{Llc-PkF3RW>H#W7q+ zqQf%YbU74Zwbj@M{Zu30HK5tdy*9z-Hz{Fn<^mASe_u=UAq`O0!kX>Z2d~q6MGJ)@ zDZ3F|T^G2tW*sQ+=kDh2=F9=Bq!jJ7W>NEuRlNA9;Q{h6eq*rWDN%VSFnJ57j6O4a zj}Lvk;E~fd*1(%dczg&F$(@-bRtB<@)}QSX8T*UiO%h=?Frf0RxI?aVkN-~1(>^D| zX<_Q*AEaChoruyCAr%$jgqli!%>Be!&xO3A?(n!>WM56ajKgiiRKjZ?>&7RqTAfKD zmg_F+QUHtNw{1d7YRpKIK zd`cu`4*U9s3lCcviTOw4?`{Tr+sy0d5&aVwKB_Lpy^bKi5h7)p^`Vte(UWrY+8*(~ zT-(~^;L8X(Mu;Co73nTFN)?T9Is7rD#34WTq0Y68+n-GKYo-mTPk2vYK}vvxY9u)) za;?Srycgg)IsJS^#Ci8*`^!dmFNo(edv_lxLw7FlHk@*j?pjb!aZYL3?tMO}YDr~7 zB?7(p#7)>2p77o;5U=JR$cTrbeI=X$Pdc~pit-dSgRydZ9_kynSfgh+*NG`GBE6cHZZ){C$HmOh~PIP#_&<6TBXFc|9xo*|{CEnJ=evqdTJWDomh( z*XKuWRKn5x!>p8e7e}+&_S~Yj`xc3hWVdtounZAv7y7O|6W9YmJG^gV5WPfhmz`W# zDUx`CDDDn@<}(|(z{>076YOjRWLjOPd&aP%r2j=-CUeW?IWyTkXT#ySY4UO!Y-=Z< zS0Uv#WJ|@U+dY;Zrirqho6^b|-Z_dJ2wx^0mXc92)Ep&zxV7uLXRqvJTGH0z?|HT} zyduS0ZkH4}`P-{--!h6zAM?>MXV}74HQd|sHG-IO=c^a{PYw92wWGAj42fMZs(PBO z&p*le2+Qp^Za8<#SL(LJ3!_Rsr1-C;bIZAr{tp>iRs%w@mfDNUHIzV}2h`4^b9o;! zlg}5o3#+2N1n#6OX9Ub{9W;c7>o1WO^8SjkiKyrFtoRNlf0FKV@R(#OS4aE+{ zk}oHAHJy_C(VuB+il_hVZxlw|VNgoX^vpn|FM82u2C?Pr(@TbBCRGv7Xiqx(5i8wJ z@nqUF@uwb<(=$*T33V$$1IxELD38teb1O^HpOlc@5m5WQ+|w>-jgb zHqs$Jp}**;ij|A9zADP1T!PcIf95voO?>ZPdo0bKT>0fiUT?}~-72n$Kk1YDqAH zj$WJ{$MNd`Ey)UZOe~V)#UpeOTkBUH>bczMvss+=tFluXT{G1FdEwLG#2@YrxX$E@ z>2yNXba$O(MNcEeAK$obzgF1${h+HP4Rv9*Bbq0du=TQumF2Q@wWFV#V*&pkb9l+q z*A9aSBsOPZ-(c_w6|(bGmd~vIo}O^#s?btv$#x6bau}cJ3CZ{7eBFGiYh}efexh_b zKbN-`3t~LE-FW((wX7WSr?kO@64u@(s=I*fhj`rF=avk9qK&2p@!T|aN^zgea+6Js zi-94fce5_RL;K`Y#cA5{q+d>3+SK#(uQxTde=uMt^&PU0w4}85Pxf}#&v|cPjZ6=lsImbLs@jn@2tbf+uxH{tVT}Z7~6EGWB2a}LRFo!MkiWuW9 zl)&b{*pH)pb5vzcdGQ(LfWIq5ATTT;dn1y~AD?Icx4=5bmZUWaJFca<#vz~_8|(Rt z^X(ti77gf6$h8iLV|l_J1tL*gDEw&da?;#vkpjrJ)nIsBcafA{c`e)2qVd$kJ?%HP zTO$EWGwzmyo((xqy12ElEUdQ)%|y?2;++jY7H0(#r&t~v*}6P5jM|OjwfwyVf4PX) z)RUa9!*AM&_aJm-$!tueTEt)A9Uow+ufV(-^Gh%u{q|hwTl+QehR{lO#@q?6pCyx{WlEge=0_xMzy5mcamfj;YY5{@mC7o9 z$j-~kdHu0HwS8?$Y$?3Q+KYWTbe=WjVXpHK-RlGQvLx|=S?W>$&xs{Ehi+Pc`f+D+ z?WbW9B)H4Qv%jvWp?hiZE}#BF*f5o^tbf{=i6AU|PIJ{d*R39@3$jUO!Jt&nyn86O<;im*$nDj}T^ z_j(!Fd#=(f^>DJvA3a2?y~hxx8PX$<;FL4Ef8<5B=kh&NyDOxw*xpooZ;!?^I_HqS zeikm1RtMK!#%)LQ8i?l8nm>1zotjJY^{Fa~bhM-C%nM-6~A|4}1AbTSc=W>QVR+P_J%}-j9LpuIm()ToPymbP- zg9OD_E4*!g3*Lr(>+&vc;rWHPp*eiHsc@VjVvofXrLa>TEoFu3_f+tFG!YBM-o$^# z?s9`^y;j`sqjQ?yPSCedW)`6<1E;HMEfj}t@1af}f|>dx#5rp`w`P{0 z^Tx6v1eA{1#dkWV;ACN{tHY@14Bf`$)l7JA?pym@89TvUg9xvE$m6sAZmAzX(;qG# zErZPWzL|OyX^rxDvDgNE>n_8xj2gZaAWBNY=SqPJV4~&ki+T`^gYh1c#;1~{_*JXb zIlAlyr+7vqgtU_etgDZ3zjMx^0Uw4hIZqx0_+mFcVc3WlA30kfz#z;Mu`>A3{kVrM zdQfwq1m!HT!ix)CR`^ABhA~@LtHt!#lsv_9?+bh83olRSA&anNCr2}9_}MMQBiWCA zj8)RU+4hU;k&Br4J?LAaAT(9nDA64ytA%8-{Ci4A;T&ZB1_*fPq0MguMMvpcJ5R+Q z&rOs$=hK}nn$CEsaX{$!7RNfYV7;OD&jW!SELMCKZ!CR<3nVRlB|IZ+&ye*jXjYbb_n~mRt+TsvCMz{YFY2$l~hWd<8ObT~@x& z&xp-MIbJ{}=w(Pbqh1@iT~8kwa~t^LnA#t}ROe%+4Qo^WgkT0EysOL{LmMX)i)r3g z+SUoo4pOeZ127mxxb=pXhL$FfeS2IR=1N$+PFk~VW6vf|uAJFQRrzSn2=!;Eo0!z! zUIf$irIbsPN$+wlvVSI<{Ssr8w18igf9jL;jQT`pZ@Z_|CtTTo_ydCo^x9*Zmk9!l z3>EA9uWKnc9xkw1?yDbRrY_D~_=)B3=gygVUR|3wJ@LNi(n*B6YI^z2c=PKmosL?o zFI+_kZ5px@q~9L-Hum9NXKuax4f?RsbSa{GmC_cVzGLQH<&pH}&dM+KbGK=pc4Q8( zGtwshxayNVBl%;y)$G=aRKKi@cb{khlPmg|;445&S|aJvZcyglb2EQ#e-dl$S$V~} zu+y*z)8|&}v#{>AYAqlGTmi@{lLtJok9ZhsY@z?cg~N`>er#N!t^B~6+2;do-zq1G zZ_=dEtGVz#x{PB_!GqjVXySBUP?(hQ2118g%oJWb6gv0Ax|^2)+XL&jrq7S6BGKit zpY#^e{dtAHA1mKZh29cc!$tBPxNO|xYSHTwLxgpaqL5pwvJVsCaW9+q8K%RYg`W(< z{drF*BE0d7obkOh&Nqz4#8R=nP&&!RER1zTGR`7$hVNuN>ILKsQR0;-19)UyNn^5&&SG)=T|ZbFybvJ z0ZwbE@~L&8ue!H|CllWOcxYh8Qg0Wbd*YVhG~DN?edC_zAcu05rt>UJweXHT z75p6|6AC&+tra$iLea$5Z6DQB>L#+En9@xv2=R*e%b&bHcbwPT)7e+a((XIEJkR)f z68j6kqF90eMyETvQ~@T>K`_1feoV^hH@xoUAWX3OXW+n{7) zJH&r`p^%exTengVr*uK)x$T+OsPS5f_29j&qeNxs*%gDCU~se)H{^twfEz<*Z*ikt z0~X%G_R(@C}W9ZhD?3`NHSL ze!gwb1b?Ht+nGDJork1f(HeshAsvbThpTrFYx2yxhu^8A%&3JrmZHd^)~URODpI5z zLV}hmGggTfLj)mIRHD$zA%s8Z}Q2w>T^?$}xn4}XX2+}^FanzXFj8S3aD*)h#kpX)hqKN{g( zbKaGuqdY-_tcqvC5+sqh6DmG80={3j7|YoK@~e*17b>l86@Mwcb9Ex7dg}JnHfX{p zqr0@G%S)Yw&`!h4J@AZbK#W*F5hd-9GU^?wZ1UNpWH6L%9rb;FqGJ zTk9%^CNdpNcqXFT`Qg@_W%QZ0hzG57#s6T=7;bj0JNLu=-V+XVdN^&0tI0$0Nx=HI zL~wWPg#n=24n~-MGyInVIV&J$uXy}<&d9Bc+#y`K4!>Q%{%RU^QIgw;^>f{32hv5h z)3$)_4=F+zbp>_KQnJz8;BO!1O4&J>gatZzw|!va zTOUhfkpAuAeDWdp7S*#)4s$I(sT%8^H}pkTOB(BN#^!riw-SVE27Q9C3*3R0sLLmi zLJ}coDr#0IdL5S+2%u6fUZJ&Z-NP7i&lJc`QKDOP2e@B|E(eY!M?MaVy{wC%YMf0( z6^f=Fef`-nQr1}$4q?=rg8S$%pCwQgMh2^QNHtE#6gF*?IXS*m#i`zNNOt217f#<3 zEyjv`yc~yF^T#8bLU13^JymyL3nJeCgmEmt94#h4NP(`20M#(G9H0isV+uFEaN`8vSfmrs7Ch z2=7{kVI$>A#`OARw*Xd%9g8 z^Nyx{y5v5w^~c@hYX@l$te`jJkg+zR4OJ}xCFD)sC*nqXgRVwMN1RYWxEe{vD%Fhg z4cX=&u;l)RFTknamk|Dv;_HWdC!myzBkrficC!mrZ!ophL21UGPm|w(?_?+lv%a&k zV(}s1p|BND)!h~RkD!7y#njnY(-O!@Hm;73S8%38VJ~vqp{Jv&-wBI7zVokFfB89Z ziX+eGJ;_FPgS^2=o`3WCcCSK*xb$){`_o)w!rx?`@-vTppv}WU$v%7Z2hSE3)hZ6r zS{Ie^n5bDy`y{^*2g#mAX|~l|(21(v4=5$7bS+&B_zUNN((Uu$H!pEbJRVTCidtE1 zTn&q83$rw?5mnDf4`VF{SkIP@mu&kn?=qq|HnZ<3z-_o|>&!*O#P^N?m{ZsrVLEtv zr?DlR{Dx6O$A#PqIu16<2!%J5SBjWj>o`vS!15%Wz4Z1S0)Fn}rFidnP3RT$RqU1V zpbRkg#IyffKQFmSn`JQ7TGAiq*zPqL-W9lCJsHru^>UCz5k%5;ad+l&_sArXWD^=Er5 z-ZFTBW`|d({`hy;EW_MLL>c53OO8WFj!zVd^XwIH*pIhDmft5>*`{p%Sh(shu*1G% z0t(oHn`MzMtnM)%4O%Z;yLj^-7AnLuR`?v0JMetpep?Zy!}`BvI~JTn{MrjrN^_In zAa_A06C_uk)bC;*=RJI-*bz{9r6xyvLE8You>JlCCn>Z(y)ZlT_Tb&Z?epk~)Vq&5%$$_ki!o|qKrr?1~H!+yQhXmN)3 zx1LJ5y3YKi$h;!lH19vhVr4d04PUTN@^VejmjOuaq%L_=uxVZ8|DuRwH z>+zA`nyW6wgOE9@(5!)J3Fn2+b^Ftsg&Y>Nj&L2Zzii>;@K`ybxhq^z@Bsj=$$*fM z>@`HDMB^o7>BKkLe?iv=Z0UMC73d&@vQ!BSH@UBCI=7z^{?0ew${oj%(Y|boo zBsaR-8_L;l23`j3&)m1TkZ!++v9d@lrhsD*V~y6oH( zN>&sxBIC|zBZLGA{G%%*H_F@4EaVh0#$UV5-aPb3XdT@X{%B_C75rbCfxjz;E4J&( z?2;KMO_*CQ=P~*@y6VoY!?N8A-D1;;$ZBxpLk-EFld!ihF5f5smz@8L43Sr%PZome zMM%%J^GlHwy7e6X!Z!m=iAzH~#_h4qK6#n@H1C#Fx+i}(g+GK1+ZXzg+m;u8S0BceaA)MO zo9CSQxZR#wvC3g%8K#@-x=Oa4EV;STWxHU1TyzfTE}F^y zQrLDqiuG#lL0iHW4H(vSzo*o-wN?JN)XG`;I>Nwo$MiV-jrI=?K2-AM(ecP#w0kLj zE`x+`R0qn+BRt2?noeQ{C9adq$NlIKzO$P2@Q!!FAVUrIrVM|gZt^ZA4qg=WVz#=K zbbOI?0WRl$UW!@IWlTN7v!FNjTgdRR+8$xLksWQp; ztZA(}q-xvsm@QrIqw8f@a6z@R^mnw;7OM_V}Tw%`Rs*!AY=g8sexqGfHwM&Of zxodo#?Ao^LApJS1X2xn`>sX;&7iQ|FW~E^+vHdiVXHL&G1t%VwoRJFV~b<=!|jYVD_@+A=o}^bp~Mhu^s0 z^gX{S>SvjQq&K>2n4Nr--Nzsc1eF^MgnSZ%_n9m}#R#@|C_Eh}m2U7CSah86>csZ@ z=j{U{)T`?PO2>+@hznc0313%9W_Ij?LNy09Nt_BjH3z{^PRs>psdESS{`5TM-L|{a zp^iG(CuR z&>b7@>l)`*wbgut4jM}H9w_||Qnwm~@w)`Y{7sy-9CabG(;AEolfvZ2^X8+B>3I(k znk}7M?3Ws~?=~KrycB5q6W_8iY_YqDd(ba&wa7#AudNPQp0Y4T{M4wQW)m2)RMWV% zU?O7t%y5$DQu;tLN}u!g#RRwp;}>Ihq>~@1!p(XGN{2*w%z|3pwQ$||S-go-ozmQ^ zZnlpht9QEA2!~(>INS2A@Z@tY9swfDkW=3#ChR>RM)1~b?3V(%QiUR!zK?* z)-w`Ach`H|A|}5&eL`7ZKpGg>SX)!w_r!e8excM5^qCjPIt3)H$9Adw(=bVP1X|#a zgzvhtwZQMzsgxI^*G9Kr=|vBN|1iI?^28K91iEHH9c6woCzV}w1}~g9e^sfh?(`hB z3ouT!`?{a^Zohw#((VpBhgY}vD-XigM7!5UtS@bjjblNe06Pgr-!pYV*J{z4;o?^+ zW>BXyaqsk9KmQxN=$YWTu432a_rdfcC^aLJs?20sgPjydHPhymQcgl3?hZf=`$(^o zk)lIkcZiE0NUpj!;JXP$^02Ap){3Qj>ldBPS68h9u%y{F_>lUulY1uhW{S%j6_aFs z#MB3y*T_Pk$4mSf&suz;oVBvLy=KM1bKengZ%5)1jZk|__=f-&huAKp-RMl~+nd*3 zV^0o~QpE}PAjJYe(B)3See(yp%1r;8?1q0b#C39Hhq2E_7yfWBMdu)eUvsbhTzs<6 z=|>OD#G_JE2aLpxkU;=tj&z*GIR7578c z1+o2-6YT+i4Pp7lQEqRaY0-l~S9Y;_khXMK=97elHT(dMkLC5Nu%C*I)Zq>hBN$o? z20Rxr+gN&pp6UV%6Jf24&#!sGCTq8)o1Eo__w*YMl@)-}I3<35`7Y%rf$H9RwMQc| zk#-PJysalet$M2?d>Zz!Y!`lJ9!QCf3%E6e;_nf=b_YgReN&4f0m^H=lYC!SmyTk| z8Lr&VzN}RQ6EAby`q6ArdSt?bTMl3{%Ni8awFq}b4+jw^w)FLN3eEM)RzbWSQVUE= z<3(1?Fk1)IK1v?IT_a}#kfvQ5Y74h@_nDa(qcUnI^jF0~qa*yM*B?K}#!k;#Pbk@o zz!BlT*|%iDaoBcs-8F`*@piX5uz`Ms2db`+j^2>6HMRSr(lY&vd1zm;*-2G zWL`+fl(3hNlo21cCIk5cExJ0Coes=PA2R$<`378^vJt%ha%jbx`c2og=52O zU`~bG`zEZAQLF_!MI&`_Z@d!zp%8ebjyF)3;qf@5bcG{GA<_YR4hXny$ryYs=dk1f3WTVw~8Mh!`k9-7~-)+OC6{)CkA#iVXSLK8LxJ zLyVj$-6qj{PFbSl=rIW*w9-j*9Q);F^l*^=PbD$=3T@w4S6XV zKLdMe_i4(w70g{9XWWNH6(9>I4i5I0ji39xtrXE0Y%GsN95;O^d=UV>tJA;9cTL$t zys(h(4}}i`&g>qJ{)5M%rPzxxB_pIJ7~apkv8$?Dbb<*4@DmZ6Uuwt?NXO%u+6E-ZjozL@dl7|LW7!XF*gYfbqmg^#_QW6xs!gU_1a%NiacN@Owixp<1Nog zybSq2HaLWP>E3fXl(ng8vffLTo;H0r)O^l(p~#g*21S5${vdXPh42f9gIh;wO%b*| z25X4C-D#iFE)F|ba)ESf^-6zSklel1;7X&-UH<@hdwxN;h-Ny7S#38}$1ta7F%Gl= zJW@4LesLgexY9KuzE8%eIz0v0tB~N)^Jg6ax zKYKhy8{TuM$-6t~>?H5}pRj_cGMS|TYJj;c|JmiLqKbgv7-4ecFve!I>!3UGX^;YD zA4JOj1AqQaWv;BjpB**#l3n}W^=1Z_QI#z(;VxVYxi{fRWy=>C+CPirJ6zd)hFgW` zr`6tNh~`=k13%eUN>!p~5!ec4SWmyF>;xsJ0PxV7IIyPzhYq+Y4w-cHK`NX*jJIBC z9tNv#O%Vd*Y6`Opmgy-AEJhV$R5}N2*_&?nmyD;OJy)p_Wy#z7Dngof5}b2hOYBS} zp){5n(X& z(JA#DA7}VP?Oq3Gu!XGW%0bT0FBrFLK4By0pH=AYdT{^lH+h}YE1a2kR%=o5Kj?#n ztsWBc=Wf?y6ZeVt)9tRURkb7MT8QX$!vrIpe(}3*Fm3!;%kz})y4itld%BL|kW<=q z-{VS4^LpC~JHp8a)D%ZE=V}-Nm>|a-C@z)j)E*#7iML*5-s#moi2VSmc__a&O$zC& zec5U|`8;v|zNGhHpLx17t?w0_2;ZDUxe!}6V$7*QyfDcmj9hZv4EVo*+D2RJ0Uj!y zDDK^SoUjwX_!}Y1d$Vj>Zn5^B9q{_^6&QjeRU}$QQs&>B@bjA)ca9L8br3=R%q#WyJ3vh#52v-Y*UeVW2yvtXGlW; z&RsaLNf_z#SGqB~`MByNUL7xKGCaGET8#?Mi|Atj<4+cTg@IVSt2^B@ydk+n-7Oi9 z^b&j_@{77@W8Nnox?ZM<(%HCAtOUFXFDSK!stndJn3je`WuD5K9|*mD$T4?5?!&$N%%hITQ{qQ$7=lwNM)1CpojdHO3@ESM%X5oo_`p&Km zt;9#}P4@5AxVoC<<{NR@$xZ&ZJ?qnl&)r$lbxX*hY#ROFXD6e`TVurO5P^zmvcx{tJ|3u}~q;>Fw- z_tcE&zxHHC9JFlc;(pTT>+gSZPvTVeIk0Jh%4a;?!CFF7w3-}hgxjf}A*7=(cMWT{ z2~k~|y$^S^dJFcJm6-sQK$MnmC0wmIs}b?f0 za;N`sFQq!2c#zg$>&_Rml6T|Y-!<)Hx!Se?o@O}%U4-KYnu9EV#20>gcwN`6ZPf#3 zuzihaz%^h(sf@_Y#69Cf8hF^0eFG5ICpMXaI)K;^OUG0uTv&L0UI=cC+s zZ$lkxD35B$bvHG~6{&CpG4QCN z96Far8(L5|gHz3sk)3F#r+_lC*>}I`a%9hWr~MF2bhYgr zI55nHKHH*kTR90^==@nHn(2JC7Lo1i`L7`XIxk`Q64b=M1$atyMX=@fSl#)L-=xzh zvI@4Wn|F@x>?l;7WauQu8!XGv6VdXf2H}Uo_ex}+y`=zj>@=<%U{#GyEmV)3NSOP4 zG(KfsZ|1ns+?$f_7L?QZyArc6mzSw!N0Zz30&m2OcpL3!3IFY*Qq17_9Q6SfFo6P2 zwh+Co_1SsSvM?=zI5bfjQrr=4IxgfMD5>2rh|eh6(pNaw8hvyQbd>6RY;DlA-j-(`@ZTNJjB30{sCl2u6C zqf$%!xDlIoBgY3p&5!uT;C@dYE{<4iP_~i>InaH}RCi`3M)s!|s0d zcY5zQ$-=Z74)XyynG49thsddGjxRM_F+E594h0L2vf=KNb&N88ZBZMVhcbbgf}k)o zWs%wI5D2<5CgJm~-xW=Kwa5Sc(Uc;?*G>-T*7`qd*DCu%adS$xzA>7CD|M2$#q{l zU=g7&Quep^GhA9eO3%KawWlrpPdF=)_|AgvhKKsi=;r+Zq11Xd8TKX^%{9wMTNWQA z*jj@C2i$jdKado=wDH68yz6hnvacDC9gGwKA7*g&lHRjuE^X<8*A<3_hEHRGI!2t_ z*lK_A3aC<+7jF_SbD?WyGcSoSu^R`j{iReyHU9K0joZfRRHO3nz62ScgspCAy>AyrV!Taw!duj z-WUql8rMk@uy+fFS;tlH6%5hSr*R*%tXmuwopD#uf1@ULFI?m6gI#W8?plLuEY)mW zz9KsxvRmgQ39Aa5Y^7-pwtVbZv#I*u&!>BT6`?Njt?uN!<&BKE@&Aj%dk#Xqm0`G_ zMHX8Ho|0FDCf@Zr4Lf{7YSC z{NFeq_6!a^kObJ;p~8O`0iwKm{c5yT`C^J=u0e-Qe)90vM<5tS>;cy-qRs29>>wqF zle`6*!JJN)w4MrBIs-Y@%2VdEH!iSN9@=Ujzg*aEe1+%wgVOFv6Jo!SIa!bM44MgO zjED>abBpjf#-dZEERW#D?e`~U#|ilb2GmUM@I_!-8NNT%ULeu-cVY2vo-BPQ2!q{K zAwjJn*NMqo7e~wH%swXbIfn*C$c?4qib3=-(9>Dx`6kn?DqE3 z*oerstCEV2FNn{Se?DCE3TR)z$`Q|3pN+5(S{8e}^bwnYM3EiT=W@>eKF`TL%RzS}o=*gcdqBHYc(QVOJbnbJ<$~g=F~0+wof~jD?0y4uV@{ z3T9=pG}H3I*1rBeLWYM&Wu2uzOwA?_cSmTh0uPrZZ?iUx9hhEt=3vQad1kx3BwKpY z6tb-IKn^xfTM@!p#!q8qMBotEQ0rAp@tQ&ntZZ)GUipLZ$`6Al2U9-tWSQ=GL!@8U zFZgFc^!t_L#Ct5!O`~s2EcrOyL6~5=PtP>~z&|Z}(29XeeC2^C0nE(Bm{I$NU zp5`c?n9v^SeM(16*LR`7HODZN`*zapU-Ubc)6~G+ar!dw6`!)cK#6a=pL{;K_KvV^ zE+Ij4AbO9hv>DU+L#*^^dg@=9H*y!t2@k|jy%CU#1=F@CqkmT(6_dLchS*M1K;|8L;j=xn0+ip*Wr693hzgC)#s5>u+KBG-^07Wtwhm;sFPE-w~60o7d!C$mk3l z@~)Xlkv9>CrjOmks3(w0RNkctYsarBgwQhGg;X2>ic71Lah`P`&jofe#4H-;RUP7w zjT)W%iV6Q@G9tRuCO38=Qx=?tw}Xt_1Rt(X_`o0b{Mde)INfA01HrCs{+|UpRvbZ- zXj(I*r&ODcSPzS z%rFXv0st%Y*#vE;zt44#3M~N?y{&LXr{_s3;)E})QGcKJP(7Y+QWDf$S#%0 zguaG#6#gR2&z>)dWP-gbz0U(w!xNhtS<;^m&K-;bt;>uSXrn{z52tRP(yJLQy6B!* zmb{Tvopb&U*fyW}m^3r~6kiRR7dmIYF>EO)@7;VO=E=2#lHZC9cf`L|1YnX40WCX? zV-mP`H0(uKi%#7Fx#mbiO2I-4Vl)fd1)Y*;)jHUey|h%x;m}5qiPQhf%sM?aTyTo; zr$KAOy0viqWX5a5Lgw&x*9a;OLP4Jj_lJ(}a7@w%6qY5HvoeX#H2k+&@6j%ni3)s@ z(wA!qt*@Q|58`}Usbe&-y^0gg7(b9)^J(IaKKNy37dq#z{|>~#xyo*J18EEJ9DV1^ zaB2}oST|Pd{F;^T5{u(YEWe)L=A?^4#Z+91*Mh`0Q#G0FLRkkI9%7ot`d{PF)@(1J z7{kczW`3Do2bZ~rCZvPbJu`687%WAa>wkAcAi_I)W4>!EG@U?$;qQkj-D!zEO&j*? zLm2XY(kp)Fw{iK#^^IZlk@zr`s0#3X9LVsD_8+vdqWLu)aDrBU zxgbWMsy81QUM&P|2*AopLFa892j6*IxskQ>gz-G8;>=@uiqPLvN~V{RR#8mcevEn6 zdKDCT*;D>hm4_TyK|t0j)YQZ@xx({-Wtq{Tp=p_ROhS6*arnbiz-2olj+<8M|FyMX zEtL0#?n}PvJ_`Y~Rbc3H=TJFZYcMoTg6l)BBa+EiG7|e{B8qP#>uyF>k6aX88n8a{ z6@Qc$A;pwb7T2W;6ZhY+{|wwwk`DcOf(hh8Ms}bS%)8+rmWebg!OioKDbu5E+57N- zOF&w)I3{L*`$>{VR0;1PaXLj9po#@PEau|hxr@8$9F$*Men_A)R4#^M4; z0?+%!e(2{5(%aPb_ZE|E=g=X|qX*H)1C;OxrcFeX$o~)UiWTyxNL=JhR z_Kwbt*w@xxM4>xN8hc&P8TX z7ZRt2U_hioV*ykKlJdYGfU!o>r^3gP(EhjIed&-eI8@!6{m1B#02Ke_EXnz^3KJUl z6zNB<$0L*OcRhI#APnM_%B996qdJCn5T6KwVwC7Aes4>yw9|om=O7{+I)Uj~{)w)C z5kU8AV|^hDPTKd{$k9WVmI}~sa}i@i#m$`rI=U>bE%gD`j?`X@DD@(@4v@k~(cG65Cb-@_{$vQNh#`MLslgF{BOB#} zD*zm~0mB8+ZH4@M2o_;>IObslg)Yd-3Mwy}F?(o;;_$UBy#$LgI8t z@Epvfs$}tjze*m=J{$O4Ga;wPDeDQP4zPbR9ZYf21&<5LeLWPNFpHL#E zT(NCBRjW6X-K(aza!%>_DsNR=NS-U&inMY<6f`3BtGIinb2W`y)=qM7^{T^FUEn`J`^V9Wp|q!v;90&1`Ru$a1k&G}YyyW9*c?No{mFx!%A z?v=plNS*i)?;c6%>f=$-t>nYN1tD<*KJr|?liPLv->(ZqmkThe5Oe&nd#fCbV5$c^ zT-n&sD5nw%&7B{`@ZYuMPK^qa@R-VFKrrjsoE(#;Lr@4hiJ%TnpmD8%heC_Tm?xnb zdyS|=2o#nHJun82AdxY^3(Qyheac6ge3>0T$WU2C(>XANHrohWa&9&cxe z`>NjD)ui>+N7SMTJ2&up@r!p!wS*batq`nmaO@rT)@8A8N!{@dQfT0+oRdr3A-ly3 zEvuPGt^i-2-H5VAvxPYs5k}x>bbs1K!A^nI1a3{CFA^@>H_((h3aJK!^z4KRAan(= zUe0og_}Ctwc$KBJKVYQB8#Abno1V~Di=$@WKDp>_WbaD9+t*(!&6zID`nCV-S1aIM z_Rl)n>E(IVdn=sD*Q@L17>W=1JHw`S^pO5jsF4TPGwnGBvE9w`3E`&$E>kd&KpgHG=buG`g z-Ui4|u-@@uF)p)bAVJS~MIv-S;1Ax0#tG_0%aR@n@J#uuiKTo28?mvFHD`5)s zL1>d_|B$l-kTcuqrcVqx<*BB}d&{6q4`V4p#iUugD2~L!QN#uH-`xPIBpoabZFLJ! zrO!VrjNjdMqRTOsb`jOQWd2rlLKE932}@J}I|d}Y$I_cZDW&2N=y`|WT8ruGx^0^K8e!^wx0C3#IdfligjjFf@4CtuW4HEvRa#^M2l7k3V z79Xd{ewWp`ZL0aRe@E+ z+Hn42mMj?YVeS(U9}FAVd403S5W{B9m^TZ0MviBYxy;EB-(vqg+>>bNTTf|qN?tdE zT+YZe)nrgS{kD0yqHDB&{95Hk`RA=pof0nOc?fI1nL!;DIalj&JtT>~sFO&$Jx6X6 zd7Fyj(Rv`*?ij{-jkIrtUGa=n%|S8gB9vUrZd4e5?H)(!{He3BKeCqU4FkKxyJ0!+ zx($&12MPEZaQ%M0JAfAkovGyn%n63|FAm8^sVOu0OAItcdW+!{2N;koZIi-NVr=7+S~^lKhKEar3hijMX}&^w0${<4Hc1uJo4j= zl3GzG3D14~;5otmmI0>|+xnP71oE2z&f;|Q-I4QmrU}@KsogPx6wtrZ0ga}c=7}Of z5g~Q0;reWtYP2d2CxrRPu;*|Me^_XGfd!5f3k=cRkoC+k3tJ=hQ}6ewegQocK}uco zZ@sHCeVPDM|0~5n(-GQqtq@+VMBS7BSTrjkU*NQQdm7@oA$bI0lrdM(-%hHS_CZP~ z#=dF-=If{B$zK#Brz_A(o-9t6Zk*8atXHtj8yaOeS5USrb8#P|^NUmX12znhDTp?*- zrcc$fb&V|}q3#6S%DepmHQMsQ{{6<6074$?15^?=SMyJ-WH(?73{3=?H zoCw?F+2$M(mi_M@!L+?M;=eJ80z#K@f40Xj%mL>R=z}%vn2+M8i%m6v&-(4b?oBg_ z=(Hu35XlZ-`arUOgm(X^=n>Nk6gF{i`OYO8R@HL0&ddoBp5{5q{HkUH`U#pgv@%(6 zL@EbRW6iS1=)ClU;6!KdEwiji*ky$=bNLK?{UGpoPBJJu6|_L^;jzHRBDSCpu#7sr zKjrJKl+kac)pW|54WwydL6P^1lReMkIkl@lw5@K8c4sd#{<4e=>2vx6Kx_k8EkuaG zfUf;0&%9z$XH{S7RBQhbt3Fj6lw6&nxV4ZeG<=5%G}8F961#Q+_rl*07$PFhqni>f z&$|4FM_nVDaTd_NaBgo~k&glu34hoz)`wSBqU+3;grI0|%$X?{F)@RAmxVez{|HTY zgBL6&Uz$!ZqKMOeLx#Z{m`qYlk#0r072Mn!>lO2TDrLTQ1pFD*Od@i;K zr!xu(DtWWX#s=Ice~g~~mMX^m|I#mZdF5YWIJw&M0+j1tuP`TRhZhGC|2>sI(}Fn_ z%NO%>E018yr0PBsOdQQ#y{0gTYbJ%&3)4gVL2ya38nRdhp+1>r#pHaIeU8EmHjSp`730+JFvgRAP*pSXKCm8D zjp;o*2lIYx#=sVIRUy!7c45FWw={w?a?;KujE{KdA;9{8I0f2_OukR}Ik5n**6s?mrj4X!y+Gob z2i8c0G-sFtyrGoG`g+lRQ)d^)ePM}xiN!G|>zrkTJ|(a+Z&EZSp;=j6OC8gg#m{S6rZ@q>h!gz7wkZ3lx2YQwtJ@R&J9fTAZS zP{4k|6jnEut+*B~{J1UnzW8f4mqEt;BVT7}Vutr_>eS4|y zP{IQaUGD?yh?u9V2&D6{rbl#>J_cAJNvn(;JW>)Mm#I(?xg642>uI|1c!JnFVOD!$ zCk~!4iy@RJ$l9v{Wv?}L)|2>h4=Xc+VOlOFBonyNINdZ;o)}`9C1hE%%*hbl)HL0J z8ElrHnAK^xca-?~JbPZo=Ea27Qv2WG@H~R=5{}&8M@bko*0^fMkI=X|U)Q#V)+`}4 z;|j${I>efeW}CVwd%*xM%SlqSMTba02}p%9xWG!uQjpqmO_6p=K><6W4or)rUL1;= zRh#-dNM8k7b@l|ffRq55`Iv@&2b<1)p)-V*JKsR@79=Aj*A8++B4tm0PeizU9awP5 z)rS?cgP}Wl#d&w*DO z>XK>?nsD}TdtZNEdDp6cnsI|Dn6;#lAI?>)a5DrO1N@EQNI6Dwl4#6LBJyAIbdCxc zJ|uxVu3Vgr1d3Jn?b14`5POT znlh;ix&^}qv|?fFrA*@-jDps^1qR~||AZ7Yrzu0d(70TlTBTi)=)GV`0Sq3xb3ijo z%a@t?VzKrA1SDqGaCPs5c%eR+_TTqAyLPcJ(pGc!&ym{MzN-#n_IJ~m4yUIc?X^yy zi#42NTd2#w-|e_>EZ7?fYPv009|au;@5N?yBgeuTs)o9+w&^=RPjHN2o)^3A1@p&9fTGoxihkr`l?~= zupg(3ld4(atZdbz+Zh?<@;TUG*aGvm@n51$h&5aGA_)9KmdAtJq77d-A+RfovWP}wK|2skw zDh%wp)bKqe9`TAOGXr`h<1iGmvtST>jI8B#r&>14NQQKnx#(GrzLDp%>Sd6*b1KpD z7jtPnx8Sf;b=JPu^eQpX??wlheR^behss@u7~g=&`MP2X49qr>1AVH7E^=x(MhQ9Z z^zivu$?C92`RWnHXzOC7E*PH3>b z1k)<|2*R5ovekbcpaDD+Vkr1;RFAuBX}wCmETO?sHjXCD=qTZM^DGD+n}3HC0cFX} z+X1WYuY}*a!+>gZIg-_DHbGZuE{&sT<)kju!h)P` z8XrxkM?>@K<=LvAAZ99_7Ed*^evuJ)iDf>plLT^4?nEan)pU$wWD!+ZOLSnfL3{YZ zH(J2>pi{xc6i+o+FU^cH$GM+j5tpm7a-Wfo4yA!RDe zHzw88EUj2(&ZW{#>8oH;3dr#&eni-R>dg8z2+yT0s$Nvs)_oVo)h}P^oCYw#64;kx z0RLL#Gmwfjf>3Ou;c4`xTq!KC9fmO4f)J{A!Y06YvIO%*fi6$&&L-f^YV1mK!m@0( zc`2vd-Yqi2cmx$3ZK_MfMw3^wH0BzAr<#c$cWc5qV|m771M6jdozgiiC+c}Mt6M!c z8W}$)d`(DhjsHTk)L>!GpiR6nQ)TLN-NNvS&IaOmYrOwlgUug$ftgDfoHM8|i75>G zCEflo*)BatTxF(|N6R{1QjolYUNCUMq+ZUX3sns(GRg`<%xmOx0Gv8+H_~S zfid4Ie?2%WkC{`<%Ep<3enE1=G%q=I-BbU*|+2*5rfnvMtdVUhWqP_lYeZ~%KMQJ@*792y%}k4gGsl-gT$ofN zOC`|2KA0M4iVuDQ-s=2+gQD&o3GGC@0%>lY`O2RE*ppJBAH2u1tc}5{)W81_ipm9o zm}#Yv!hapFn7Wi;w1wbA>-ieMVqx^++`-jhSSAE^XNZgv#ENc7sZS=WRV(pwk`d05 zuc|TRRkXD^!+_0h6Y+HXJuBl~!Tv*#F1MXVsW~hUG|s6Biq6xtxzV|Q8OJ3xudF&p zhMm>%EZH+dBJ<{HcIBCP1na1ho@lZ)$ay#^bu76?O|UWfF@#sw2r9ERgx~tSF^eE7 zm%^r2a?u29gQ=6~WT|2M=9cD~WI1xk9!8~+<|u{coKfECfT>St{R;dN!8R}A{j4+D zI1~j!0|pjl37#wFbTVs}!k-5{Dz#;q?xwoXYFe#A86}LvCyB%+tJXx#VF9P8i%e98 zq>GFU?wy2LSvB3HnWnBt*Y3*OSy~ymE6r_1~*9zbOu!J^D(HVRrSv zYbX9BqdIR_xiv7Nvv)|GZsh&Nx?{J8TnU?;z|S~GBT%+fDaXp!!xcI03Of!jU#0lI zu+<#rY3VlN%0lqbgneZm=vS3yPEE z898jTL=J23Pv&&Sh`uCA_yf5T`Emh^*vDAPlkmrtsO3gdXd5IZP$VRpyp>IZR)^zE zMl*6ST|w`JMtPc9GYt;S+Q4U+HH#(*(3p_`X%{8#Y;Zj!IpqqJO>IZ3cx-5vV}E4j zTI{+68Owq|u>l;DUOCP@D+9={<1 zskWZEN?#c@M6Vt=E!d87Q*0ZY4eS?u(!Vwtsv@1*vK39590Kv$+rS}9fd9d!CFL1y ze4;%{(XPbpo!<-QB9WdVt!>L<-A_c3w@X+>yq&YEMYOHzSot!JZp6x|vmVpvbV_S5 zO*cVFQ?Qi4b7Diq(-SBaCVVygk**=|4X+qIt+8|Th}v9BU87EI1yP~%@5U>znuLW? zA8RxKfs9d^JDWUZ{TGJUs$W&}MpN0V=M>Dk=dI$65b>yj1G<3&slcB25?}cDW5YZRozdE5;-cd;>R-);P|AtQAtO6YEXpXXz ziO=)yHY?swOk3QulMs^MpB{r0NJOkcje~ua6ydHdR+E~0d@N4 z(H|3`A<%nlUC&l*ZM3dDO2`YFa+JWl;d}uj&S*p1E(wUX>Fl*MXOFEO;fYP(uv-;h zcJ^8xgK0^utF}QOT_?CTnqy$JjfLLMCKfO#-0#?)Mr2|DNp);E8Z*j=wZ*K8T~q7H zt>n5x0u7^`nZbVkD3Vmy0`#-05ni$ht&N{kvvIs0Z#rJ_ajsg(0Kii)7bzhn;A>?N zlvx(9P|Ii!kP2grH4|6EhIAa-o!2~(oA)Q|YQNl`+h-cC-!XP5yi@q@rEVS=>E0yAo!#HgM(!a@z@7 zZSI3CQ>0)Hfxg5RN6By&O63S1h9YHByjJBd9aeq1Nj0fk;Ye*dtAesR`+Lw?&IN}O zD@CtXT8AG944xM>3)h}xf7qf_FIY;RO&;A8Ch_OrX$a1md-N3BHfEBvDBdzmov_tb z$TkY%8s5w?!EGQ@+d!sv0-1UVaK;Y_=VDjlp#P7(?~hCR-uK_>uCwj5Q|oN4GJotG z&(_&odOSwv4{+Uvn4I3C=rsY3K zch`*{?#X7!?1^PDRg9#SO|g1eUz#n!P{=$#9oy>#Zn_jX>$U5Rvmp3Iqn88*wNK9m zJ{4zRl#;W42F1=*#TR$Sf*`Td>leDqv<@n$QB8MsJMygR z=@R5B6K*nt8AC1uySyCw`nzxx%$ZR7AyK;T3El0B*l_!AIl(P+VQ=||-Ud*~(e$Uq ziRh+Y-OIOPwm1bPmpYvnRc%g}*U;Zo>bE46IB_1Vy^F1cSkTHV>(2)CcQ{El?If5R zCoR7MsyIq*h;q{4S*j^39f&me>+a1vO5ka>A9H9xozRk_zIV68a6u1ROM(N2%(+`# zM<@~@<`yf5ji?nC^m07(d!>~if0k|GtN(y^tv+o2!m-Z;chk+;Or*1iVJ7!cXf9`6 zL7r_IG+!d!4c*>I2j~fMwDG)=1zxK;LfYi8&=?5fQyl+q%)oa@#WM3sp4a!l!$R^n zT2(9P(K@YjO`JTa=fAtU%RlkJh(u*f;M1k^wjmIjgz}D5lmX{X`)M%X^$xsxJn4-! zi91V1>!~4H{q%%f7`RCgkktJ73}|;E8@^7(-Wrj4146bi=O$L)6VG{K*~$eJuOYrK z4C?YdF6#aCKBNNRB|rD)5DFo*f0`v-y5-ZmoaC@uNNF)v4|@VRdaJTR;%+VCJZl0J zU0<_szK1EL!;S3g?=EB)!a`4zAxJN|Ki+`WBpk7?>t&H^`Sz`BZAU?TX_I}B(9Vw8 z;%+`%(rU)VvlC`WAzay6`&eiy0M^6uM4F)#+Uq|}e$qUPmSLsK4%EOY%9SXYt7Ax{TvQi}(P&x`90;0bI z&n-V2fDu6Y`19pmavPW)yvex1fay>w&y+8%`QvHh`RCra*ImRt<{ag8T%)X4qg2d9 zNdT9Nw7MnW;>!qr>8L+cqPND_aU(Yt-aNG_%PVxy7eO3o1aTl{{uZZ!jU+q>fLb{} zWBXbEl(=ZGKaZ;BEE2OlP44$qAxd>MRy@|jwww87d0nTVI*m2|M97z$M&QG;R>iF= zJw~Hz8SOo~f!lPbxT)!bvOK<;oh?(J?{VbSk{O@$Sih#xRl$7+uKY?8zp4?&H4xnF#wLRx?T@R{h z=!Ab($?sJ2e|mnfvU^E%-THNsseGqr9#o!VU-LGXf23cJklWTRHazI$hbopN?SEH(tc=)Gh(gF{$jRSudUKM*8 zlRgL_0$%DRFqSpKNJ-*E3KugIVqh^DG<>6*28(@DBQZOP;bT=v|!8zl@*?*sg-~VTn1*d)Ry!IuJr{ z_rBRk8a3Qaq~t8mL<2(#k%_!NIOTbR(*PfuZpP8*)1JeQo?`Ddm*6l(zy{Roq!|yG z+NYX3e+d$8XC5EEEdFNZp(*;lwR`mc6fn>gM^-=?&W5y0RzuVxv;_Wf`sbPZzghP| z+*bFWeX%>^z(}00zb2wS$f`4+ygdN0D&rR!YsxC@?H1#-FsLX&y72y0YrB(okVnP& zduiV40}YP7bEH@B)0u{~+2UPZ;(B(Z=CU zDB%x#z7uTI5tMR_9T{7{Pwnu6;>D!(&bz~4Le%6m*Y~Ec#M-2gG+Rs5zUcht6}NXdrxPJ#+bMfvFSyOc{P{WW^CLZA)+u=-&WDTd$?^e$ zFXt=gZKAf`xbovt+WZChOv=;zeGlFtjJ);_HQH~d?Eb6A`{*ceW4p9RzT|kL$M1M& zX-nYfHp8!fTip~rut57+BA~rXuA1+QwvPBP_h0^I7rOV01379(JaTB-(_yC=7IJ`U zHX3^r)9CK9t~H)BT=-5kU?K`)91l-;IY^GLn({#UHEPf%KmXNCdeaxwCQ9zjYC zu4+RiY2PzRV4wy_D9pv0_jy|7D)RJiCr2ITMC9zB;v=<7?j%`&b-t&(9a`pIj z?<>`tJr#{Wv^h^FG4G2Hfoodxx|OlQr}FVl{#(48Juji+SwUo1jy(U&dHcHJGhFNa zpQ%p;xerx;yBy;R$piE^33~V62Zc8mmXSYwR;WVK==*W^U*<=&^Y1Y%(8u>eGxK4z zT5(3tAls~EH*o=RLQ~S)jyHmv+cXz(p#pLh&c_4?^WA&z^r?Bb2~u|f0NC0WdjmOF z^~IlmqP*p~o{MeoNyj-n)$QlOa7!?LT^M)w8t_5WWu5&3 z(C$tdeaAsXo+b24?ww;M`JJ9m`Gyu_fMn@mgE8U0`sz|lj>5_9Wo6Z$zw^|Z)_syc zOP-Nns~l(5*{GQplfg;?hnu8T~7bt{!8F02}56tM6oLmV3b}b zjuZmy&KbKi!XB^49QW)E4kCZO`^_!&#J^meySV26L2*fUEK6yw%m8w!3xw!pJ68y| zbH;D{A*lrDEtoyvji`r#8E^5Uf75B`B9U(VCdr@r@_zrE1)^q;P6`pdE31j+vJ-1WzQ*^}|7 z=GZ?yS^3(1)g9fnf+wFcReiVu%%3`a^uo%F&X?WC-~BlDPp{qBc5KIQ{v&_u2HawN ziAPs0cVjRP1f~c4^|13#Lq>M6L&+ataG;#~Z2GK~TfM2FR-2hHFjb90LnvB`YSm93 zC#~J!k7WL#-&Vu1_bSw7)YYC|O4mLy)^-FMhi#)s3>0>*{qW+AI>xXfiSNTh{GM7k zucEUb0gxM9v7xCJ(agG{_8PSFMC#3#ilpI|bTQo7pPYXeTP0ClMhOE%hg2=uK!rQq z?<}-4NmZFSZFR9aN#Q_++^IU(w~^&%R#W%_F(cJD!{{hLk&62^@Fzu6{9Uqr!#8c& zB-_RAfj!|Qfk93sk3aL;V?X(!hokvFyKC6Hh4EpkhdsKB^i_52@02?z z@YzX5uSI6I-4NDd-d+pqM2bC`#bl*G5&}Da1wo*iOvWOfLE)U*$(W{#Sj{s&EUXR4 z1DB0Vqmx5P8Mf{Dl4`+`X<@Es*IxbLCrg+O(i=&%M!JeIr3s#As0;dB=afJqpcY8T#_Dw`P$sxq(6T7<Z+8 z6_tn&Gz2@H&9-Q+M8^n|qWg*JvJl(GVySS?h)Cm}W2~WZ?=s{vH0+%ZN}WvAoOzGR z70?RU4rikKfOc>IX+M7n%lHw6_=F*xj~ZdIA@R*7k^r3Mz)AxnJh}M1Qf0Fr1!2FRI5fOPa`B9jcjCEE8X0(w3PlzyLJ8YB$T|-ADwofhsWDdinhJ zTB?|PiYdG@7w%`=i`L1VmZxuLNKatV+_@5I9#9&dB<>ivZ7mK*h&E^0W}MCl$-dzh zl8Bw<+#|Zkl$MXHo7yS_)F?G8!}*-^LG~5|(WOFTgeXL^w}%-jfkZYoZ(t)qTISyG z;|;Du>78Jb-Z?8c#N&(U_ps{m+QzPM_|K2nh9_V6?5(2~Bum~j>bS%-s^sO)^&JG- zyBs<`UyaX@9x;w*57Vw_=i|n!&n{hGd<93Y9xae}1jZDa2LdzHR0z(T@i~@12#5Ye zi`Fjg++~aP1`h<+BJU&&>_>`Z2Z(2cX|La@Te-mgZ2VfeqDGa}HAg7CPd6v(2Gs>7 z%PHjABv67WB4Mmxgr=@(jr(0Ea{HbO$9lB^hZbsCjN(wWkd7@Lq4vEN^k^}$tAj(?y+?b){^ zQ^jktP)v`js5$hN1kmKw(8@alyPxgBuex>uG2 z>j>7C^x|Lru+;(P=-RfGi>27c^wZ_Et?_X1K!aq{InA ztU}RQs?N};x)t9}sfgB23QWbh!#9MnDxXo7H3UuQglY#0B3LWO55H73!YB|fjkh6F za!!LXR;-rbBa+`L-?v8UoS4$YZQTZUtbOf{w3d+k)&hN7d|+xo+s`b@V zOV@oD>vVC%dLWk)) zAyk(jr5xBGZJn=Deau1OMBTF}`8)DzdvY{ZlZ$CRMQ_X^BTsUi|MO4R+0n*Q4%ZWzjDAc&DUl?Swd)Oa;Ow&@N z{#VZ6nfr#lRXpADmN=&R8`LXp*G|U1POH%IsKn|~F^Sp!TyDKi)QqPR#k(fS>b=hP zyCuUoaS18YYQh(Ec?r_QypD#D`Cti4+=k8ZSBRXj&uzC3gdx^*zK)F_K07P1s3MoUCS2 z?;sLREC|{BdzVHj=X|nZ>2<$ zOAjl+tLRYaUEVbRW;a8KI+-f|0%naGNE(!FJ?;ZF1w% zsYkm9)KRIjsrysIvkj(|wg=DjZE8%yf}w^o9H$+)h+mmYT4!bMj2zh|%-ibQSX?DT zpZylKbKmd*xqw;OU>%}Lc_UPLqNJHX=?Jc^FJRuI_G%1YYeK>cGX4sRcdV9?n* zXPpRd4?EDaG**ORy)PR-7b?B6&pDXAW{d5 z_gUZga&WY~CoV(6T+ET(5~)EsP;#IC3W%P(&pJ-)Lg{?nTI0Ih+Fra71YO!za>I*0 zxTMlyQr8`C<|Zn+Evl~}lacAia3X1Zxg%48dY?cQgR+8PvN@Q($M8ROy~0x=0I7WM0oy#|fA;`RRZxMkuLh zQ+NgP!){WgC#X?6uLCB$B08!o9HJ%@WL<>ZMspO|;7ciL*pZ90eb8#MQrMC%_a@PS zk?aLFKG#eU#q3`sk}K!r;1)HhyY4L1SP}uU7%+Vif^20NHN9%vqn%30JSzWuIeDbgHnM=N>@_ivSFbGoN?CdBBcxqVD9DO6oO0_nky$}^8OxPNaRn( zP%iO@M(1FR7-16{mL^tn(oDdY6fHdqeL@{1KrJpjTV^&E@h0gklM8Q)qq$zDC_uy9 zTUsU0a|fh8EEL z^BQ#$0S>xERczaV_?@$f@HxPnqXU=4x(G=7_WS3~PKb$66P)##AAQVCHyq zGtgt$Revw%vBvM`=QDQa;> zfw!*xfGFpi84v{Ce|TItkpOmt%r!EK3)Jg!(b9GF5o8F)_EbdU*!azkwbFW_ErU)U zwl0UTmEJ_N2TNe#{5|8aMzfdg7lazeW4pu%!|od~>1YL&i0yMSDZ-H>bv{7lCkf|+ z8>a`cP_*i!fliRiZj1V%H2Y!xebn~UT?2VboSakJ@xH3!h_m9c$6kAE_v<^d;;PZs zRl1)%Px~lvcWQDlTqU311m~L?qurwu`>kJ&S1|uF)r6-Ohx18c5Rf{5&OnouJcsFPv3j(bl$NfiFEd~;R& zOy0r6i!$zH#d0hbk-TN;By!=5keA!x8q*C5XN;e+7CaW59Jx(#39sxCnfyUrzxFap z&-Iju*ontg=+A4oEk%-nP!Ji{VtO{)ty0!xQkgu}SNv~9mUe!!x zzh#8K5kp^75sfn-oAT|G5QV(kRz|hzJXIzNoM41Vh0P!W(4T5F3S&Agq)hRKJb}*B z>p6%`=!Y>N4HdN2#jJNS;C_+K>2wzvn&SCdG*S$LYch&o8oc&~y@pBO$gnxTXb+F8$4z+|;`S2+|4+E{;&gE2->`rvpv=+w7 z_yYq{;DU`O9##VAyguiEF3rzF_1>(`KHVg58SaK)68`NSl zLJR*YicQM}_J&qJFWckl>$cnq)%C1vtO1JXL~HA0QQ9H`9qa7H;gl)mih8)yETveS z+l%@WU+T);0!bBGVT=@n^qP>WMrudDl%k+fE5RQ0)DGwvmF{=mid*}W$1RR}-Uvu1 zJ*5X79(DOE$ID1y{he@OfH)-U3U|oMM78|`hBX1nMMbm8otpbjzG}>8o}a3nY~#c6 z#|AWU?BO@`geI+nRmn5JRc5u9M6N^Jj<~!2B38jPa6+NE3JRUdFwE5J_sWyt@cbm4 z%DIuA(7#Y5G8(hULC*G98xmsmkambIvJg|P3Ng%ybl@=YX~q<&rLZDeNnw%iaw1Kk z>{hRn6rCKUUf0N*4ANG#b!r@annmKK=@{swdyIi0!S3Q(4SU*hP*kWWRSD^LqmLg1 z%_dh4^f7z9ppSTJIh!8zdnyHRQ2xKLZcn!QEn4$o^qTa0c!7*QZEhh%O}`H@~T+;aL`oJtL0h!xEv30IG0>t-PgHK7olM?rjYewOuDFBTSSs7l_Nt- z{Q_Evv(3S{6S#%;Cq{VR63=Piv5137@B1!EF>DqfjNb+hrt2qMq**gyapgI@YWco*T{9SAbNxaJ324+%t^-!o`Ffy{v2>`^04UWlLw@ks46_dWZJr^{H&K z@QUKZ+}PR4+tj64<;msxd-NnIA*r4E(QF>5^C>8U>x4{+vJRXc9uF(Kq(w{mU2bO} zhu-jIBfqQGw|H45aX5tmf!%p#d0CjTYSdPRlt%$Yu$*hk+GO-1Og*fZRZrF(MY1nWj5i}s$8{uhSf}_X7e{oAd@VrOPX?Bz#Djd5`z7yPCZi;7;W$0TT_|C zbZfi{J}in;(5&a!Z${8;>Y!R}*nuw12C?4&=~5*jQTqpi0%h_=cfZ7MSR5X;GO$At zQuEz_z?QeXFA^0_%>w-bu|@9cEw{=3zAaPLPFE3nC+5pH2u|}pnq!KORHDvAWJ`(M z5&$Kk%eA2mvGI{fJM}#RI9k-{urjDBV!kcTtO=gA+9s`Bv?j3!%6PaTBDq?UhYFRI+?XW|$UE-Rb&)oSIoY-_fQ!cQbUd>^{FM9fMk zB0c%SA;JYOXV!C1T@P=JbKW?Mf;0(}btpof3m@gMoriLyEb8k^IyxYlxlXrt z^gr<6bBpq4A0*;zi%$!7wOWEQ0h2qI=Vel0j5BG0tvW0k<0Ee(JswrA5@pgvq=q*wN412SyUg( zSr!Jl76mME_a$!%BI;+b57^-haWg%eArS|pqlh*hnBh?85h;AhyRSiDV|^5U$hIQj zkFlIC?@xy7omWNi4`gS!$@0xX5+ayem9#JP7Nv{AP;~j*)kC?8{@=JY3xQXlJW2nn zEsk!It1MOZ+4~2jApU_^&9u9>*_CFqYh3Its{*lu<|MFqXW5;?b}BbpsZG>QY1%s| z(Fy@1x~#}k%=wN93{ z>CxtY6EOeW%ZBiLHzwO^U_9A%L(27j8exu> z)mZBYyZE&OBd#sC!;>;eO2NQcfu!^$k;9nCEhIUKRM#cG6m&odV-D7V0xWKcI80aD z`}U;g_M*Giv!5h3UQ;NjodsRkCz484APYv`$loQW@r3p^RHPPf%O25IC6?19H&e{l z&!QxYPgBh}I^Np76NP-_(r*+51o{N(&_z_}gP{^4H6WPUa}$B0Aa1W*A=pjb!lmN%>w@q1GdE z5umXk9H?Gqxoq8e#m}n|Y2Ze@I>z#9W3*&h8`?^+h+>rf+trU0?43nmHE8Pi;y}(j z!tw}d`_&5}djiRKiMGobv=7ZM;}&A09~#)xvgm$fSf;DMx1*vEP_edSe6C@}$bMXL zmC(zA)n#F@XRI&?9L?K9?0{J2XmWus!HR}(Jr!*=-VQM=cy_sjZm>4KRO_Z=*-=Ph zn(YqE8&Wql=Q)Y4?1NP!Qc?l}yQT{dh^0*D)&h_M$`6NxIjmj}d$Da^A7}Q$UOZfS zOmmjFDaW97B}(G7wF5RGdj4tkS%E$8JnM=KLk2Sk9*o9FHJH~$rTS4c*G25%b(N~J z%Z1x4zcAwS3e?G(gAILDkyLJ$xy2R>BF_q|>QPDDvkg6U+JtnqvP5YKCK+Gr>mnYq2%U$!hT zg)AUb)TCQmMIc?5bXxbii>vi<^72_3n{!6O=Iv}~if__tLHQ`Im=tGb77Q?I%}tzS zcgiEPo;^{YxsiQ=gv+kY+ik<`-4{Zh3;g9SF`vued5gB_!X=AW1Ub7zz^Gz};fiR` z!=fm(DR3olslr~SUZ6OrzllM25n;eT4iAC;ioPU8c4(EbF*4s`z5L=VO zDwD8olr0RWLZ7+MtuE$`Iwe4u-hp7;UgorOd!sfn$xQ!j{iCapft8v7>E1gW+TjwA zcx-XUz6gs-BpQ57`KOB`S@vjiv)Pu-gVysNAagirsykvgi(CiA|qWJdb>KC_XL3fHl-;k_H|pH(n2;hUN24E%6XtzdsxFUot%WJWGcncGlgD=# zYjU(0bId)aCUZEfFl^(kcwfDr$d^bAiBNhe>tnQBn6|Yl0ZiKsQ90?!pl~VeL@~|RIBDcEa}}C=)c>mRry6yL2QDu z1>`mL0vnsbP8!-zt~`JKy!IT`kz3Wv*>=N~Gua5Y_G4WZqMDxNqBKZdJMU$RX2Eyg zh?h#C{=~;4vG2|zmBEoV*!oVe00wP4lw27;3PUD6PUPT6K)EF0Hk`yAUn0+Y8?9}F z;<^nNRo1i~yU|*OF~}+>T^?63q4X>IGuo%_S?PCs96maV3C3lm49v=s5$%z03Remc z=Y)emRc3EFEbtbZCVu|tFKk$$c8HliQ1s+(0~SR8OnLjK5tg?=crPrEG{=_wHH2y^ zq*HNuEtcgB8>6|8N|_(c<4Q~7a%lw;C9}q|h?V2>wBBF3ohY>S97sw*f#wk5U4tQp zP%QuTaeezeoq@?^kAOyGmfkLO3+irpmM#Sk+P|6H;5rJv3LM+%I7G#NZ^9uzBo;#`)W>GIckMmm~_i zd5v00;lIG|*q&OH-HG zEImB}DhKq(PaI!6QCsea`MiX$?>?S!dr6=TEc({V#p|>j4)gcEfXC86w{g_HdX5}! zT8dwpjEN1;6=!mr9$D0h+(uBN`$J#-ly=MLSyl#w0Wi7-OAFx}i%$&d| zLtc0sugzh?&EC>DLnNI5-_`W+hJ;$Tv*hOLRDS;K5&zRt zQ056rS}%k^=+Lg2s-GdS-1=_9EIC(xChruTXZ5jOLD-CX%cA$5%^KIC-`~pf?SWg| zVdy2rfQ!d6z&2Z#0~Tr~wRD>|(HEcMs_)@R@Bnnx$ZIsJTyb&#!aiLELGQVoLC2@t z7(gfWnoTeYN=bS?U}lC|J1C7-q+f(CrA>>Fup!e&4%;sc$6kaqQ1)cIxIrf_A>Y`R#^dA0qr!}Pqq zHnr@^maFvspAECWa1 z|F|X)YI}!c=#Z__&2_r<9Rj7m+W3yVCDn>|Otc|o$K%sYjeanzNNPn?B4=0xZ<0~% zn!0!FTK40Srk)RQwBVXm)pb?X1h3)LWn*p9FJm74k^k`9BhqU#IcITD-IY|C_4Aux z1s_!Q7KZ08R*iV3&L?VXwcATr+B_0dpK&~wPo1ULGZ&kUEzr%tlf-ra9B51RdHUa* zPX8OetGGx0JL?#xT#~qP%cES;KLj^N>Cf+BkR*Dg)vh@i7Y=zlC>zfL_CK5Ov6^)jt2hZ)D{3?4AFx z;z#M<_BBVT%JuYU03Qo$lF|xD*0D&9DX+0=c^SWr{LHObFM&7R{P0a{*aaINe$b;Jhu_8B*HAwr z`p}K1lo!}lVHDoRl5EC`oA~xhkkk+ya*j0 zxgW=W+VbtIetnd>wCdPz4t@0aqr;=`?eHsL8}qKOv{^pc5%O@qkN*0Qt^B=bR<8c| zgV$8ra}^g^7LcZvaQ>NN#$k7SY#G2)+)ucr%aBXEi`={GjJ6PIP`&QgP(t0ZQIA-ahrc|;M9$+S|_6N6eA6qfGevePiJYdMB zh6vKHUG`)_yT3K`-?O~`vsFBr`rI8%hA+qTVW%wEcxghBROx zZeXteg6YTSZB;c;#ZeNaB&NznAzpZ(z{_O&BQ*7@!W)65tG3jI0aiY&*1Atb)6 zQ3N46LH$*Db%7{i1I~ytTVDK^Y!M2X&vT#l;&88I`D2wP+jR~aYYE4NFZ8oNg zCyXtyPXY3c!?r7F#goD5AV40x>@SlPZ`UXErTx>_{XvO*hCP}pqe*91={UQGoug}N zmFIYHF~H=hpy*}rl?Goy_o-Z1DiidW2)hjJ0J~C8mBU{{2}m$TLmv@YESrDz$7=^x zG7YQLvyrwumT0GG=Z`*8;M9F|?ebKY?%v9L|Vr=&2T}rUjsCzuX%?IGh5&nk%Tv%t$}X z5Dj@tKRoy2#c}B66}3zy<=OQe{(0?KulE`6dEJmR9;1Pt%avc5GEVI=q~tY&qIWYI z>o5huqexDjk9l0>k6R<>v#xVUR+A|1I40H_{>RtIfO2qhX&5QhX--HZCz-!bdoJnXBVIEJ(>Gqc~eej9*@eQ=dNzAS`q=S9c?oMQNQ6R#!*M8l05!WhRCRB?mZw zZ23G1n_xC8C?c76W>M3gZH?SW5RD3;1}wXxjt`&|90+wBgpN(m?(z8xXOkdmP8yQ- zdCVgVtKU1!^{1{~)=P8?V7s0J+x4D6|E78!%cwR~cwT+juO`bh@7VJ)lzeKL zjJx1dsY!hs2vRw%U|P!dFwB|_A+cS_!l)#c9hVdBP1a!|CA&cvD=qvpw=aBYm~Xy& ze7aaP^j>=3kGGmHe75pvD!_4o9L%}0ZHnhRk#DKI{8sF@@`2k<_y{1PCgMT5mi z)_cZc4&;l@I0e%|Lfuqgw29MqwssN^e-)i{-htA>xpXlj9QtISdHPgaZU3;;d2WCB zAFs`=T*&$CFudrLAGX)@OI)|dVv4eVAQ<}}Ry@JIcG)0|p9IH$R5(bNQ*dD`%jux2 z60NMIay1(-UFp^V_SyVd=%Y!D_zYD!vk7$gZ?KpIKv2XH+N9=4>0&T`fXbuR4*)zl z#NPq~=&$gKRJ|S)TlveXwst~`TtARj-kYP14{`kI-k-jwPyb+(zjpv0p4p~fT&-c9 zKHqzxA*#GZv?1*5RH)}MQ)~}qAfC=1ox1b;rE^fwlf*n&Rv1qnBki$s#=-` zyPm86>5m8o{{APce|cyN(xL*Gn&P$yEg@h1oa^HKM2jdkR-3HDlYy%;t#xfS1Ck+f zz?MDEu{epv+%|IWb7~1OqnNAU&Ii*8PVA|~E;T>b@ie1VhiR$>5J_lMTcNOQ%)$-l zHeO*?W6@AmN$*xiN&gbCwl6=9H#`*%U)AspQd0Pp%6~%{^PeJ4q6Kdezfu9j`toW| zg9Ys>ZwGkX>f(L%jz)l*!j6b8l&C3OUbxviQIE4}5*xyy zjQmK;?X54t09-^7UfDoBLXc{_g0-L%e04>ta`WNt2OhJl;u?Mcmwn;Uh@JGe?_+fMVL|uABh`qQ5=alShSB*ot;4OK1*#z zuSXR`CWis6_V%i4A3IKzeepo{FW92r6C=o0&?`18FXZGL8FB$U?y0V~iu*>p-dR5* z*kEmjCK+pNn}7&+EgF{mhFUN76l(rKJ?v_1fWBq}o2uOaVQGE6O*%j{7)E-fABd~! z`vx9Dr6+{7u(P9INQTTZ%UZbzzbZZMwJwgvR!Nk?s1-<6S*Iz?{|>K&uvxF)xrs;y_q2&6c%Io z30!2vWXY^_(Rv!Z9jkhPiWeaXZdsC=)J%U}8wcdif#VBA*3D=aV$q1ZRnpIKw z;}82Eul?c4`e_hSJXY&`D9M+!DSAQK(X@PSTbl5BS1%usOIdf*NvTc{B`I2>QDWTfI;?=v#dEnGA zgd+Uwk^56WJ#nq%@kQUhg}YwTh7f4`zqPvjRrNL?#V4DH(G$W>q^ft9XGIPOW>Q4c z@uw(j;lNC9&@FtXH0P44{r#V#X~PEqifG1&M%s^rf}WvEmI!=gil%(_nc4D%`d3WL z9A$v%85n4;$?Y&+cG14w2!O0{#6=cSaooM$&2O0!WO3 z$*+c3G_2yaCcu`%PBv=tmv8@D+-wH$8KSmZU|O8WN7L_3E{hh<%8~6$Eafml+2PW} zD->8de-?lNdwZ8kT<#@v-T`Ujm89sMwpTj)A1-vA^*&&1-FkAE9Xs4`fngcZ<9i(U`ztiRdRv(dJ_3#_{Urr08rw)6ZF^;uZRsRjrp{ zCmPWII8rp2g94}%u*HOL0vMxQl3l0+ln7T@9JA+4%E;1nlAz@~cJ#oy8-|UkB^u<~ z$8rCbAfK5KU%O5IO11tQLCJl<-_x^B9X_hc9X>DgbbEqFv&9d+Te_@^EqReaq8IRZ zYQTPI=9nrnAX~Or#<_BtL2c+wUdHHGh&+sXFWL-eCV&IOTe{ASqg82nvUC(UDfP+M zlnKe{7x~7~xym2g3wgNx6P?$V{mUuZ;JRZnfJ5h`f{X=@9BN4iI1J#*@tM(%rjplb ztWYOlh4LtIlr*vE0G#La0MKb}ebKHF7l1V_V4gE)#4Ytneh{-n4u27&jC9e|)tJgvbXo-)&#tacnYbh=K9eJTS@XLEu9* zmr%K7tEKc|+gY*+Pw)>Cfam3DSwF3E7513h#C)}LG& zhb?=dPV=^W5Q|%w6W|IL;>xDRdUa%%MwUXwhhKuu4FS4j1^$-PA_LBkw8cxv{pM+b zHIWB~Bs_N1_|yaBiy778V)gH%9}T_xp3zb5zH>W|-w?1W15~fOONmA!Q}kPzJ#t{m zcF(=kNs*QF^UKpjHWx|E5S`_3?s85D#L-x#7R1*YFLs;`^#RJSspMYc)TAhpvaBLk zS9p4IZ>l_btbbEQ2A(@&K9_f;dAOUqP7Sv+&2zJ&}46cHs%j(Uj}5yA6=BU-F?oxde85UxBWX2 z%*Dq^N51~^Y)ccbF5n_B6)$TdyE*?a8n$thVY~kUcj>{xwf|W2X6baX_N)3WPscAa z{btsG1JaefKQnYE!cvl*Q#Ed{~OuK*w3v#M#YB^bU zNrN=!WmN{U2~tw4nMxkPEuWrSPc10I1fR^&i8ue=Nd4X^`2i1jH1}s^NROc*01gSm zTU+j_T|OlPQ{bM9s!g$1_zzC<&vNEBmlrYpRqoMv(+Et{+` zH!8PWkX&#FY)Z|QTmS`yawA1VWfKtm9qgXxdFOq9cXjs{^)Wf;I@kKWzUMj*`7HaP z`x;(r`GS*lm_6(Bw87)^6Q176`UF#o6-M3)&!o&eAWopiZWPJh-q3Nj6`9+b4@C1a zw9d}2PY4FR&qL)V;3`+`W0FZ{bi1e%fayW>0zV0+pc)$NPZ^d!Ow6!pdS8}!CxKj0 z;^SUy1#Dr2*CBZCUff$qVzeQ9Tr?tHwp*V0IUBeqGHHce)+|T(k2J_8*W5N3c*DOl03! zJ}M|Y^QfFbY&40!Y3M83fD+Z&@~ShK;s`9I|4wMj8l)3{nDQsKecJ*edz89u?!MYw zs2cun^q8`gBFYe+h!t7Jnrl?ISJq|kEi?{^ZWS-1PA%)+#F@I8HCfBQ><3s(`T>($ z`@Ogwny)JOqO^jxqFD6D;ty&|yR7&It2t%q&E#Jb2(W*y~q>=*7&Fkoi{`C?~ z4O_m5EQ}w&M!>5AcK^G*{U3DnpJDr)d)%yh*}Q@{kE#jhGm0HE8s;`x2A`nLCQz&L zW1W=4>&hh^?cOnI{O-BmvxfHhiMzZkiVF~!22M3-qu7UzMYV4N@AeBabTfcs1CBHf{gKNWuf*w%Q zv3Ux)1p^ zRl1jso1dh^ADx{~U_~zncM|~>hs52mjk}aL{cHN7f9lRZ&GMgOsxX>rGpC)1Rr6w@ zSy}W5nYN`|0Dg4^j*j8ln<7aoq0N}jh_tw5xMPBRy^6X%O(jyp& z=m*}co2X(DGe!)9Os+&ioq1s;!GebRj-l@&4Os71(<+G&T<`7;HgltUR)8S96%Yn* z;FVc*kicI)S9j~(zB#CzDC_oviXIgzab+r}JFyN*vJfM@CM3&HOb1aJ_3=RWS@d~l zepsmUO58decK^|)B<$s*P2QOYU4E^<^lc*6ezsfW{dVhr;dP!T)XOL`@|Y`L(If6h z(gdY#4Q*szCOTI}omYL(&}d*d+|Z`Jx(&J)=NBPNPfwy&np~Xx;dRWC4$%IReZ$q_ z$$Y}Les=t**gZAo5{uGUMCIJqXj`R9#%d7+Xag?xq_cFe*4A3@?k69{vut=G3@wkHW4`B7@iIHk@~HU`kco7UV^^O z%pBLG)I{KtT|%N>ZjzP{)?BK3OzyaScHvvxjp~;QcA;NJdwurVbR2t2Q%}%xLt=(D z`Gr1>*GIj#;6=?eZ-=|uxV>8lMuk*GVIE7JgQhB-`Ln;t z#PMw*Ts1D1(_+;Zb=Isa4dK*TlT0pGYD;E^lBlP#6D3Wa1NQl3zPB)yqn1`0Tp}`z zyxs)o|NNmIu3u91IB0YBXRE{Jt5@UJ!DB)dWUi7tCg-7uuS7fX#GAW{~>JUaW+J0j)aw366mB6SLWVM87``(ysn}kgCV3AGB9~&ukc64#7L1BmDKa^4LipHdrx+SC3^u zjn~^bWQVF%ttof%B zin>A2YiiC_r39a$1d-7MN3=!3XMgABsp+KH z7?fJh(^>Sd`G5$o0x6Rf+fWnU$7brct+pCu|kBma&vry%~5Xw#kNLrZ?DTyx8PQ<>_Zz7J4n`fRS!R9%gTL_%Dd6 zt7iciGBh@phc{71j;#kGYgH&y(63{UDAh_Ko&!=1!BEP8Mb+a0!wdgTjk*EnmyQ30 zq#bkfv(53)W78=%RmJWmz$z7s-4lCT2Jm*OtQ5=O{uF(TxN}WdYaVdd)f+xg@{4~y zCxAO^OK`url9wX%oWp&jpADX$+qH-WRZfWQW5xDb){|@1l0eApOC8&T4b*JR?@TS* z*%xCRv=H*Di|C02u%Qm-@I;qM4|&{s`$BKnV>cj+g9|a-WRf;y$`LsZG5y3v%>Uz1 ztLm8)DQOIeSEl1+_moQoRbQxbOfmj|=gz6C?w$(>OE(7oU{Ep{NkyaBY)-`QIdIab zk?9qK@i32v@1A-v9xu?-!5SbR)-^8AjJ;VkJK<+*g8?{*@H-eCFH}v4IyzRl95jQ7-`Ev)?6cen-0Uo_T&6AXZZb9U_3BN`rsUfJebuD?J^e><~8Th2`}_9uit%lvbm za%S(pxz+y+JO6(wS?u&S89z5HCWK%R!X&+Q&xW>=e3W%_y7Mb#?P-=IF=r4;OVN?! zT9W-0^;*!oj#~csfu(}Z1bEgE<5|1++BE*AJ_MHstrS(gDCUVIuYrxlxq^FSYD&5A z1xcH(jPM7;-%fpYt@(KS)E_P}7f_&xL%m!p1DZ06%cqKSOr1ijQ8?xk6Tc>Kx%046 z1GGZLPjmz`y>>{;=)<*<)hv~LE?$RKdkH9B9%6^ zTv!j*g^v8M*Hw~)2}Hg7ZJlOa1~XeFgD;mmN6k$)MN$rNSmVXDlc~^|KaEfu&Q3+}HngDBo-5m#&XXb?iW;qwBM zEFWs48}3!zWON7xTo->YLFgsXqXD!YBZ!W{gX>t=^lW8dCXJ;v@X&jBsT25cD~Ob`g~ECluc z;NgNA{jhzCoRV~21Og(Fb?jxrCH?{i1y&IB&bs1iqcNG6z6MnK3sQ>m=kBr+b3y?> z_G5MU|Do(2+d<{v-mj0HeK*#;9UqhPyoo{gc_RgYUu%@Vw`esCH>#Ns#MpRiys%^S zP#q0PpeL{ZInsZgC7Ojg(kidj2`hzj{T*dOo-bs{3Xkoegq!K2xL);;$EOMpeCi`r<^A)ra>xb#S&AqPGrJCls{bR+QNdZu%ZU3#9rvBD% zhSOx*45(#mn3~f&QByQv{nyh;Oa{$z0m(>;8Q$i@L1Vj?vDBA^HbQ@Sn)`?wxl-N5 z`$H0QM<_r`6_~m(uDt})V94{_8v*CF^2Ji2gh$e_%|?I`a_Y*3D|Ag{<{il&V)Um4 zn11H%D*Ws#O=Yh)yh6S;e2(8YZF*WbBCAZW4FPB*4M*%^LXo@{Ou()H zwU^j@)6QWcaq@({?VSWNs09ktKwX z42~#MHlchCg3|;DP6_7%c8&WV6w+0_`76vR`WN zd15^c(uTnwC2vNTedQKuxo-DKZOqgQt-MHpN?)3%8~_*CD@DHxgJah5xdh$kYvPC)0iv4+E)d?(vjlO?P=LfXP{&n3q4g$y z7h+|#dEk|?AT1btnI`DQOgjc8g+|fEo53iurV5ju(NrMZ+h>f0?*uXWnt5n#)BVh8 zFW!0r0%Jg|1G+&5>~s1o2U;twluA;=08@y0kml{qC^NwaNKg(kDU~X6lAP`XpJ#xv{Zn&`-m+lAfx)6?#Q-#O6a2FjfRw zoNIi8B>o0T@`DQ$UnUYx(-4ml-uQ*3ZtIkFAU!bz&rIaA3SpWkM_}a(KAM-A0BATK zAXsgV%1o<@mn>Dskn78xpHk(ynCI0=TTvZ=6r>PC zJrO2nl(hCgD4mdkP%?PrFGs>b771iX%?OPWchHhT&|V${Q&aB%b=tl0~Yx&|v+knEO@? zgl@y`P6%71$;spFz@y^B$=x`LIL9tTG^1kN2-#Ql!c3i}x)WLFdn@+v+%cx;BlU| zdPnFhwsY?^$Dvpk39{zUw)sW(ktDR4c;D!y zW}#(yESU0|yWX{@!xz(TH_QrQl6J-CfEkWvdu{O!f-{Mp#g(iQ{5VJ7dYLb{^@|3A zw-iM--hy$9z3`nR zKZ6PR3Fg-yE_i5HR9#NtTOZ}|y{tzoI`l16C!J0XJ+M!7FXk3cfidA%9W6yZfw}`p0KmyIj}|j(Zf`SdrvupsnSQm(o-LfO zM4FgJdXE@z_bu5Zy{Zq;BmaDV%{#bnEmUctj*Bug_6|dr~PXBam z^BvD64UTtjZT;TrU%&ps+PdU>!@C=o|C&vOM#sXHbuNq`B3V<*i~6o|c%_+a#YD17 zpHud`g`&3!y5EZu6J3&NS~vCA)Nrzk2_wW@s~o12*q~!&&7Sj2F0b9{eJZj=h6_Gr znvk5Ce9M7;Kg7N3azOPU#n(9)!b_49B7}9RFI%6bWz6&iVx21RXQMgs+FyPhc;gTs zxqULifc6{b?9jx{+Da+ZDtoj^>&veXeX(f8^)Hre{^CD=Ja>D^taJG7$lo4merN)> z(5`u>knj_<&&QVwo=Z(kZSDufm*ML4W9O#dX%O{$#!Q**75-cI!qvtNtsTv?=Z*YY z;mPAeN=M6lT!VwDLqmRWixhzz-|s%QGQsNvSUrvIKh3=CcDol=;Xs7d#hh%k=<`Vp z#sy@0%>DYsl8T=mOR87N4)TysB5zuCuda=}X>EPt5#H-FcJRfb_!HNKK05MAGaIne zxX>kPfT=A9OcP?0VfzY|ri`8)wWM0x>?D{sHi8&|JyU2}Ab9 z9!E+~s^rvnlG_z?$G$%FcIumQXyl+XFUmwLy;Ih99@I@*@z$exUw!Nd{yw8P;}vgh zdX4*!NHxdx_{3YOfc;Vf(!QG?lfXqZOOSg#(w$JXmWc^sh zIP4ueHd=XnM6npLuyO<6VNsWul|xA-ueEJLIT9bHbnRy0k{sl7HP^VX8r(@s8(C?p zXY%Bwp7zmSz!BJKjv%s#cS2m*ONPJ#WR2pEeZScWi-r&Xy~6*fMc@Z|4}3{U7*Ob4 zj$LuRzGT%bortxV11Mjrsr7EY2)qxql^cr%snf(Zz{sr$y~{q>50vo<}s zOfp(F$?qiI2s!yf$FMH5m@`bOA%(Nkr24W)qNb|*1jPQX=7Mm9&|)DX!;8BH6MV%zV5`9;zDw91i| z7K%%i$763?yJBqE&Qz49mfTdlHm!9Fuq8|rLJ8rpp+R*(MSFgVmyX=ED~4lQYeXQ@ z%-JS#=iS&JzgPs@`q;0%7t)7(Vi_4oG#o_B{t|`$QER93S*zZ@WcJR($VD216s)L1 z@;aslgxJU`&{upB_(S9|bTijQ2Xs}YNJLDK6Xl238fSUD5gW6-N>YmPXJ?!Tlg%{GP#lNhKqUJZ!l^ za-UF@UTzkX*?7-o|4N{k+HtdW{(X-|0tMA?UcT@Mx^360+Wyt29HU0(>nYz%c?&4Q zFH~EANw(R&9j6z*)G(7=N`5QI*7i4*qcwd#0~7C>@;AW-fn|>tvqBNmU!0xHJxZN8 z^N3%lHbR&dzVodkCATWX)TB(*c>X(02m2Qr%yW8x_7(P(17i9Q80Y@ffYA zq}73rI}JB=a_O5v`-fj_O0|ZmcUU0Bt;K|0#rD#kwc8}g#{O7hlT}|yWuR$RaKzXp zlB!1YY5%$HqygDMibOtn9!Nml)E!N5>fxxS?VtOlF|hEwf0q_CI~yPszOP|rv?*D zGb8k`=V%r_84Wr_@s2nXK}O4A{Wtpq4s15+b3A1U>l#0nw3oD2sff-_6Pvb9S6mai zd&9a%!sVVh(t8O+0&m7sRjmkh;XKs8G?5=J_cdMcisYg@;vK5gYsodcGnWC?H;S7r zD)G*Z36;UnCgl^>d-v4F+l3HM$HsgjEm+Y0{ojaV)>S*LRMq}+-qvQX#s<`I_u#aVAw3DL1bRWfqzPF*gh8QybXChV(XQCP5wOrcg=wd zuNj@%J8ogaXz82bUG#Tu%_s22r3$)>GAVo*R~|lgkF!p6sW7RpYrz?@9qD&nDsZ{% z9MA1*ZMT31`M=hSmd_|TEaVI1l(J2}rp!W{wGP<#-@5X@a{s@w9;<_kVqzar{H{76 zUn~P!2b2ms`_e$0NKuS$v}dzVtTXk|1=WzLfDjv4CtJ+gf7iChkZk0e$xR6(n~qN} z{%vB1F>yE{{1W0TQzv5ILt@Iayg<O(IiB#qC370ZpYRMoetm^o_=zuS3wDnYN)#D4(C^pRi<;1N@B`gl^5|yGuU96pB*6;360y zI*H?nziW2yxl&f`stTa7}Nm zzR?v$K5nX$4aHQJA;5VMz}U{({d4c_Z8rvUDP+dK);;3)S0i68Gp*a>Rdx0JpICy^ znb1S*oAfx-=KH3kQOj{AnVPNCS-#Vovcu7WlpB4jOIerM`XIKT2b#<9ZzoE+Ic_cy z&YtOv`^onxMDaZ_BG;acio#d^+b?~$NF6;SF{|w^^F7gF;)|9&d4v)%8xJcFgV6VB zok~flFTt3i0+ktj%#V7ST_aaU2}sPF2J^E`FEeZ+M|Y$5kUBCUHZju)aNW$P!9VEj zG0(NiZ(kJL^$3Q@-W|d^@V7vY!^#}htN7v*6sq`sBDByD-b43GOf-KOwuZ074U%#X z_7V0<|IA1}4tWSn&11TU+7em{o8RD2l??(Z2Ps^7|tK@c<_x|{x!=j%iD9!@x%|9W}cle zF~1r~;pjVty>8E(kxg!QLpXCiqnzHE8(KDmX&WJXjU{JF>q|lR(dMRICZ@0Ugr(-NYYnFwH-#(*yfIq5I~)^Ud0XnG8f-{->1V6#d-tck zexK<35ozJU$3feg7O&<=Q9o4FjcBj!*)uQ$HxrujPD7QYYswlZyX$_1KeE^{!q-#`$qb!`22|(`5T*Ld`J<8jl}6T zPQGYL>Z7H2aP3g0H%g*IJ4)oKmW)4bTNqU-mbighYKaOrzKX}P8XLLaT_1OO9yw?Vs^C7`BBg~RJ8b=go&@jbtRw9#=y5(F9f_$Dfu4yx#D3qfcwOh(cj?q{i0u4k1)@UYdcr@qYHd(q^30=o4-*0W zlu}y3Bu(Z_9%)&}tTXmLCD)km9e_13jy#r5Jab~F;n6p<6%y$&I_rU{rEdq(y7B7I z9VQn8I^HKpO-83In140WdY;-lcLwL185%Vi^YC2>{X<*!NHOUsYEI12Jv>|enu*mP z+v9VSMX*`6iY0q4l`|xFE^b^f#ck*2)1(^G<~wj9qZUzmqh+BK0>$#&V>L4{>HGuW zQ|o)){eItc9pAFAph;(GXT^b?cp2|<&+>f9eV6H`?;8%ELMK(oU7;f8q{|PDyeP;T z1hn=-{~tJwkJu{zehMd zu`nS?a*fQF=6L)BFZT<`*qwYKdB!k#Q#z6naK(N3hL;u=vXr^O&E}@LmxF>zS|Rj+ zywN+9D+stXmGS4t17%Ts{T8)%EWw-@UM#6&rz`=Ys-OG@gm%AKfZW>F&CRsdhU~YC z_rqf%W?$Pw_ohS85jO*rJ4-+o#)=r<{8NkHv^6!rfiW0Hookv!mKY;PM_c72BB^y{ za*3Dzx#`g~S!L{uxy#m$J&cMLGy8!sEMXf+7bPpA-fq}?zMSKk<99Tq{Tud`vF%+POcrB`@mxkE1#9htCOOg>ZfhB7?t&6Mh1C!$arv7g>gIbk*WK z+wWr4B7A&pq_D&FTJ8^i9qAi1&Bo;hb8ofcMLZhqba?EgGnhl{=dW)3Yv*ZWv;4aE zyD(qBCXCD#4D5wDCXNT4J*wSFp~@?Fa$n#3YBaSRKw zw0BG#$-SHi?Ymdv*I_X9oc(n<$Hon|Y@XFmlJsNCsp;hh3He7mc+Ad^r%kW)$8Z2!^?_R*{95Q$bt|2ntX>9%~pFucMp_qE9qXQa6%A1;M_9dW} zMi=nTVC{8>zYMBfMbO&eJV5%_QNdSC29gi~i7XawnMDSMsTq(5lWzX)<4gw3Z!_?& z9uMn#ct-PBCe3y20%}i4?*?1tEdHc7CXO&@F zKkCSzUtXjZzC~mrZY_rUfG}(h0%*Rk1_mJin#HWlD(#=5;0e(EM9JlfMpD~*-^LC; zva*O*H9U9WBp6x7q-$vsjpRdu4V^aOF5a#A5G0ECM>Is#u+cao1h216CI=c+dkLu^ zbmkk|v)7J@qVw)u-WQMvSm#e%2llad`rY^!e_!^&6;C;TCRCCqmkrNBjq=b(y9{Ar zVP?ka{Qg%(Im|5$J(GR{^#p=Qs)mhrapur=&}5%VRH>T{YX&%*kELQ(PUrZsu5eVW zqs#_lDPnl?T3p(`)ubmwo39F3q<7qTwd|@&A$bRw_AddwD}H{CXZsR}i~9~(#=K2^ zkk)e=s3Yoz^n~j<@{UMtfI%8)c>mumn30B>S9SH>kLJ$_bIu+TpgxE% zbEilXW!KMzIJ)*FR!90?kbU)QysWy+H$d6z4Rw#fcTFIRCDMJ`)yKY!`7MHeb;G%;JQ4!mBGAZ!+$3>NbzdmoH0+W~vtA^7Z zr2$*YE22Fw8+}0PW|j=fCgrcYcfsVC=ZeLwyb`y(J^9 zeWOWcx7wR^lT%{@@x9bDwvBm#?dL!%MuZK?3pgO@4Fz3!vZM1e%qbD|xB9rEIbv@B%z0yxsG(W>loHB0Dis{SOrCvteu`jfxn@f-N zm0-&q%RqZDt!->AAIxIQ2ZiP-(Q(gAki@%sQ;oRmtu5eWl#DP(dR?MSN#J^c_Bvjq zq_7g2pS7;b8EM__ZQ*980a*W8JN_fZjgzeOc*&JSLS7d0D>(zCw$1~lp$q@vuF;zr zNX!q&T~sY?>Gg>5+_!9_I8JQ#(~<|VMJyfgYon&71S?ORqCLHD3SQV-9+0nxZa>dd zFc?U4aoB5mp?oO)ax1QDB)MDx<*>&Il62$PA1oWTjkw;fT8rLQY~-sK!n+3VmRSr? zcRNS)V7?<9!B^6oXczgVh6pIUyXk0bhZFLo0e$#c}*z=ng43K18~{GVc5dfv1p#av^5wrupuUXHAg8ZS$@r zpTwCSFEqtplbpVN#%454FZw4K$xwxwAf~Jx<9pNvHmAFg=xoPsRqKUIj_#D~nM?Nh z;kLMjC|J$KUI@7nKhSe;K-;YJJn1Dt(se0|hi!85cK- zh;Hz_T$stY`_VHctgvEG<4nmyZz=nd;Gs-TQC7AcTfUGK4S&-^iKkr(9+A_&6!hyg zekfB5x4uy>Ll-+eqh3S|Fm#st@++k7{az9@e|P&~=pe!EqXKnJh%QBTF^@I$FkG!i zTLpO)4+|~hZ995uD|eRNM>WbvCtM4?Va$G`pCXj6J}}Y$4yRUD#*hmYbe1(SSY{@4#Q0oE zd|!zR!QS7SbYj#;{d2{Ir!?9KBKK1*;QD=w6tKDSA4GmaRIxXm>o&0VFXhC*UIVj# zo9NF9eP~AL;6Mu!znGO%+qQ9G??t~H5}NX@Z@PyxmslVT)}#0%3Ys@D&&B_yZoC)X zCpP^sa69ZLXn9t-nv)kDb9*g*d`E>FBg+3yCaOS?!zASP%{1tb3*_0?T18m6y+xhN zbf;eh-Y^FZPfU`434Jt>?n0UT(AZ9Ci3R3(Fd>4k=v7rRg8nEJ#CG%@C-*dE$2KhP ztuVr8C*gw8mIJNIuWbL}d;XuO+`H^c)c|&Ew06=aQdP~r{fO+RcEN*jjKF5q zf@fMJ!a)&esJ<;!1g_uU>2ya@z}E4YvH6h`l#cd5reNkYZ`n zVZ_cB_rI7(hexM2v%3t9kJeoL!G)5(d-_&5(xQ&bOb*_g1Iv^t4|D~6)xHI?-Pj({ zf}^p!+}tZJo7Emk3N0AQA(}S`k>p9)+i-(zWKeSF@0B*29g}QWmDVDZG(19vkEWYS z#Uv*h`PzD$?U+n~U4`_brpxlN421vv^I`6EBpoqXgJdGeBIP*yfWZeJd^PpZoVHpV zz+ttBG8ePt=!L`tfc%fZ0gvtU<)KFBNIufICzh7(=t)$GOFq`$m@zFqWsp7?Q|dJ8 zGkq?i9P=GJIgp6POO5dt#jVo4O*OBi&FQ=urOJE~47a3vx$&tzJw zGA=~*vvHsGnBVjDefOZIBZY*#uv6fDsyroRMC>)`K_%Mmcb_I<7z{T*6YB_tpJ>H8+ zDPyE4Ylsxz%m3E+F26;dRe>Ycz)?S}b^74GcOO4D@vhGLW}&2r(6nK-?a1OA0k2qO zsjg)7S*J~`V9 zI%R71fM(EBv2jL;8Wp*Nr%{Ii3x-I(b*!-q|6X;UtNOl6c;oB*@Z;ztM5n&F zpJQOKDX91xtDh38^1H@!eGa4$UiNlMt#6f_-ItdwbIN$|iT=Lx*R#}@!h~j%%PEDU zUg3#?bdsl#4$6{_qq+;GlD^^@hKC<2f8cizw8ZmX!7VWxzg+-$$#n!qvNY$BrO@*aOv+OC{k_R*zI<1>hv z=zKYu=;ktlf;(3#u*OUp&BVJaEDYtj;>IiET}bBn!m0NL}r*1|o*ED~z~X==0I4Wtm~ zYqWy4xV*Htr7UAHix8Rq!87!308zZrRcm8+4E#EIHAf| zHztNS$x8;^V(D?ct#_blho^l|)N9ERXT2O0qy-0eC$PB$JK}Jw8nkKHKKXXpXYBa} zV>u})rlsAfb8ENZL60^JO-J2l*^AS_qg5A1aOM5!!3dHgCab&-)aD3MWXYr~K;jtT zPl()ab`o3Yoz_6)U6TYpIAc#bG0siMj=9{rE}VY%bVylvv^VslqBvIw8Un(>+7!&4 zR9D1_cA1cFjgZ$^W5%%6)>9gw0!(^dG`+iij9y22z&oH-E|R6J`H&4r8d|A~Rrw!JEQKQ(&!fH17}HIzf1$L6D@aeOTpFS$C!IjFYF&uyjKnFCKRS@UXioa_10;iH$hz)oJkf zTga}kN7&L`X6Up2C;ebDcLPx2WTvmBP^rd5Tyrmo5<%1#s^ z37({!ib$A5JeuT5E9UOC6!zU}b!c_}E?E(|Qs*L?-L#YIXdBssM84JVK>l;0aBkz5 zN|M|dB+#mVt{fAKC;Y00C(R-~u~53k9lOHdQw=}yKQtfs}(%*cc~ zs}NmbtA|96Sc7#)*yTHBoQEd<=2=V8$gk%wv}cUFC%Tb8YQuQKd6f8FErkn8#qx<@?Rr;irpj*iX-=r?;&X#X!_4$))r>w_CN%&(a7lvpkb36g%8290YD& zCs3Dt+)uQ*Lg@F%_r=P4`j>*&+LnoTJV={q&0F7`&SfAGsb?+f#0Z~CkW%Fzq>hH; zg`(rAba+Mf2#S2Vl_;+UdNe&F?@uk(HC0hpbqg-xu7Qfd;r|G9LYY1L)P&q9v$~FV+_l4z^l9#uN!-q?&Z< z+|nhe*l&{bFaZXwcu(K9HZmC{I#o6jFfy0Fk;4?d$gjlFG+tCaqO;NwCl0N^-zQ*L zsV2lU8rvGuNa|giT=Pmph$1Y`&gJ=>fmc&-f-Lc^<;L#QT^Pt%W>Sm=utq%|&e&g) zWB+JekKZZ<*p*#GkE;ac8&=J-^Gd?@o%Hl+<}vAZ)1`(gN;@xT>|S*^{njanVURcK zKDM1%V#T#BZk9^K!bS$*+tf6)?gx+ojrqS^xQ}F+KW}}0lUhi#unWnsYwpHOWVp+H zhwqUa+m3t)G28Acp_In+yJ(>RuAkh;U-(teS1lq_uQx3>x7VTH)n!v9AkD<29AxKW&<)^GGDanuGHeDn00O4U`>e*m>2(c&b zR71Z`gzeUKeS>+J7E^!2^0nda&_acm!D>}0$*%zgLplGj-O!E8$VQKa8@Pg8#AGDX zW4o;@lv)f)2}vyWaKOVwa*u9D_jGu~{WEq@xC_)anSh3&?wgr_?)^1+YOWHes_mre znG!Ms4MMPex%|BbpQt=)w>*EveU~SF-wxkPti(-@_r%cin{yOBqvt?(Uqcdo6RGmG z1}SLAmx7YW%&3KMlkyt~H*XoEuKcFCE4b0A5|YkxXvJysV#(;)4DZp=0H)O|l@m#& z3u*x%o!$FO4PC8o(bLDb*c9gl8t|E}q&ZZZW8a`&PD84xZmN&}Q%J7tY ziK~1kJRoyDPFcTV=oINGaeGsMc(g%X!bqvH*3Q>Q&dvpPIX(1I9}3;s!R#)YX_oFS zelXFMN<7;Q2^lkj!Ow7;aut0=sJ7a2sglAy2ICS#tv^g1fm#~xu5pDZL7|0(u7+*;2qH25B3nVgA&wf<`)6SK3@&7?Cc seC?nnSn2MHW69LkCa~z6^9J8aS>Fm)zTfu+_~UTI`KRI^&;9cM0Tcb$TL1t6 literal 0 HcmV?d00001 diff --git a/src/configs/sidebar.config.ts b/src/configs/sidebar.config.ts index d5663a0ff..c0da43a0b 100644 --- a/src/configs/sidebar.config.ts +++ b/src/configs/sidebar.config.ts @@ -52,6 +52,7 @@ export const sidebar = [ 'authenticate/manage-organizations/remove-users-from-organization', 'authenticate/manage-users-orgs/delete-users-and-organizations', 'authenticate/fsa/user-management-settings', + 'authenticate/manage-organizations/organization-session-policy', 'authenticate/manage-users-orgs/hosted-widgets', ], }, diff --git a/src/content/docs/authenticate/fsa/manage-session.mdx b/src/content/docs/authenticate/fsa/manage-session.mdx index 5646fc68a..866fe8f5d 100644 --- a/src/content/docs/authenticate/fsa/manage-session.mdx +++ b/src/content/docs/authenticate/fsa/manage-session.mdx @@ -19,6 +19,9 @@ seeAlso: - title: "Preserve destination post login" icon: "book" url: "/guides/user-auth/preserve-intended-destination/" + - title: "Organization session policy" + icon: "book" + url: "/authenticate/manage-organizations/organization-session-policy/" --- import { @@ -536,6 +539,10 @@ This guide shows you how to store these tokens securely with encryption and prop Shorter timeouts provide better security, while longer timeouts reduce authentication interruptions. + + 4. ## Manage sessions remotely Beyond client-side session management, Scalekit provides powerful APIs to manage user sessions remotely from your backend application. This enables you to build features like active session management in user account settings, security incident response, or administrative session control. @@ -660,3 +667,4 @@ This guide shows you how to store these tokens securely with encryption and prop Your application continuously validates the access token for each incoming request. When the token is valid, the user's session remains active. If the access token expires, your middleware transparently refreshes it using the stored refresh token—users never notice this happening. If the refresh token itself expires or becomes invalid, users are prompted to sign in again. + diff --git a/src/content/docs/authenticate/manage-organizations/organization-session-policy.mdx b/src/content/docs/authenticate/manage-organizations/organization-session-policy.mdx new file mode 100644 index 000000000..a8662a614 --- /dev/null +++ b/src/content/docs/authenticate/manage-organizations/organization-session-policy.mdx @@ -0,0 +1,329 @@ +--- +title: "Organization session policy" +description: "Override application-level session timeouts for specific organizations with custom absolute and idle session policies" +tags: [organizations, session, policy, timeout, security] +sidebar: + label: "Organization session policy" +tableOfContents: true +prev: + label: "User management settings" + link: "/authenticate/fsa/user-management-settings/" +next: + label: "Hosted UI widgets" + link: "/authenticate/manage-users-orgs/hosted-widgets/" +seeAlso: + expanded: true + items: + - title: "Manage user sessions" + icon: "document" + url: "/authenticate/fsa/manage-session/" + - title: "Hosted UI widgets" + icon: "puzzle" + url: "/authenticate/manage-users-orgs/hosted-widgets/" + - title: "Configure organization features" + icon: "setting" + url: "/fsa/guides/manage-organization/#configure-organization-features" +head: + - tag: style + content: | + .sl-markdown-content h2 { + font-size: var(--sl-text-xl); + } +--- + +import { Aside, Steps, Tabs, TabItem } from '@astrojs/starlight/components'; + +By default, all organizations inherit the session policy configured at the application level — covering absolute session duration and idle timeout. When an enterprise customer requires stricter or different session controls than your application defaults, you can set a custom session policy on a per-organization basis. + +Scalekit always enforces the **stricter of the two** (application vs. organization) at session creation time, so organization policies can only tighten — not relax — your application-level defaults. + +## How it works + +Each organization can either inherit the application session policy or define its own. The two settings you can customize per organization are: + +| Setting | Behavior | +|---|---| +| **Absolute session timeout** | Maximum session lifetime regardless of activity. Scalekit applies `min(app value, org value)`. | +| **Idle session timeout** | Inactivity period after which the session expires. Enabled if either the app or org has it on; duration is `min(app value, org value)`. | + +**Access token lifetime** is not configurable at the org level. It remains an application-level setting only. + + + +## Set up custom session policy for an organization + +### Prerequisites + +Enable the **Session Policy** feature for an organization before configuring a custom policy. Navigate to **Dashboard > Organizations > [Organization] > Overview > Edit** and turn on **Session Policy** feature. You can also use the [organization settings API](/apis/#tag/organizations/PATCH/api/v1/organizations/{id}/settings). + +![Enable session policy feature for organization.](@/assets/docs/organization-session-policy/2026-05-21-16-43-01.png) + +### Configure via dashboard + +Once the **Session Policy** feature is enabled for the organization, you can configure a custom policy for the organization via the Scalekit dashboard. + +1. Go to **Dashboard > Organizations** and open the organization. +2. Click the **Session Policy** tab. +3. Select **Custom** to apply org-specific settings, or **Application** to revert to defaults. +4. Set the **Absolute session timeout** and **Idle session timeout** for the organization. +5. Click **Save**. + +![Edit session policy for the organization.](@/assets/docs/manage-organizations/organization-session-policy.png) + +### Let org admins self-serve via Hosted Widgets + +You can let your customers manage their own session policy through [Hosted Widgets](/authenticate/manage-users-orgs/hosted-widgets/) — an embeddable self-service portal that lets your customers manage organization and user-level settings. When the `Session Policy` feature is enabled for an organization, the Session Policy widget becomes available in the Hosted Widget portal. + +### Configure via API/SDK + + + +1. **Get the current session policy** + + Retrieve the active session policy for an organization to display it in your settings UI or audit the current configuration. + + + + + ```javascript title="Get session policy" + try { + const policy = await scalekit.organization.getOrganizationSessionPolicy('org_12345'); + + // policySource: 1 = APPLICATION (inheriting defaults), 2 = CUSTOM (org-specific values active) + console.log('Policy source:', policy.policySource); + console.log('Absolute timeout (minutes):', policy.absoluteSessionTimeout); + console.log('Idle timeout enabled:', policy.idleSessionTimeoutEnabled); + } catch (error) { + console.error('Failed to get session policy:', error.message); + } + ``` + + + + + ```python title="Get session policy" + from scalekit.v1.organizations.organizations_pb2 import SessionPolicyType + + try: + response, _ = scalekit_client.organization.get_organization_session_policy('org_12345') + policy = response.policy + + if policy.policy_source == SessionPolicyType.CUSTOM: + print('Absolute timeout (minutes):', policy.absolute_session_timeout.value) + print('Idle timeout enabled:', policy.idle_session_timeout_enabled.value) + except Exception as e: + print('Failed to get session policy:', e) + ``` + + + + + ```go title="Get session policy" + policy, err := scalekitClient.Organization().GetOrganizationSessionPolicy(ctx, "org_12345") + if err != nil { + log.Fatal(err) + } + + if policy.PolicySource == scalekit.SessionPolicySourceCustom { + fmt.Println("Absolute timeout (minutes):", policy.AbsoluteSessionTimeout.GetValue()) + fmt.Println("Idle timeout enabled:", policy.IdleSessionTimeoutEnabled.GetValue()) + } + ``` + + + + + ```java title="Get session policy" + import com.scalekit.grpc.scalekit.v1.organizations.OrganizationSessionPolicySettings; + import com.scalekit.grpc.scalekit.v1.organizations.SessionPolicyType; + + try { + OrganizationSessionPolicySettings policy = + scalekitClient.organizations().getOrganizationSessionPolicy("org_12345"); + + if (policy.getPolicySource() == SessionPolicyType.CUSTOM) { + System.out.println("Absolute timeout (minutes): " + policy.getAbsoluteSessionTimeout().getValue()); + System.out.println("Idle timeout enabled: " + policy.getIdleSessionTimeoutEnabled().getValue()); + } + } catch (Exception e) { + System.err.println("Failed to get session policy: " + e.getMessage()); + } + ``` + + + + +2. **Set a custom session policy** + + Apply a custom policy when an organization requires different session durations than your application defaults. + + + + + ```javascript title="Set custom session policy" + try { + const updated = await scalekit.organization.updateOrganizationSessionPolicy('org_12345', { + policySource: 'CUSTOM', + absoluteSessionTimeout: 480, + absoluteSessionTimeoutUnit: 'MINUTES', + idleSessionTimeoutEnabled: true, + idleSessionTimeout: 60, + idleSessionTimeoutUnit: 'MINUTES', + }); + + console.log('Policy updated:', updated.policySource); + } catch (error) { + console.error('Failed to update session policy:', error.message); + } + ``` + + + + + ```python title="Set custom session policy" + from scalekit.v1.organizations.organizations_pb2 import SessionPolicyType + from scalekit.v1.commons.commons_pb2 import TimeUnit + + try: + response, _ = scalekit_client.organization.update_organization_session_policy( + organization_id='org_12345', + policy_source=SessionPolicyType.CUSTOM, + absolute_session_timeout=480, + absolute_session_timeout_unit=TimeUnit.MINUTES, + idle_session_timeout_enabled=True, + idle_session_timeout=60, + idle_session_timeout_unit=TimeUnit.MINUTES, + ) + + print('Policy updated:', response.policy.policy_source) + except Exception as e: + print('Failed to update session policy:', e) + ``` + + + + + ```go title="Set custom session policy" + timeout := int32(480) + idleTimeout := int32(60) + idleEnabled := true + + updated, err := scalekitClient.Organization().UpdateOrganizationSessionPolicy(ctx, "org_12345", scalekit.OrganizationSessionPolicy{ + PolicySource: scalekit.SessionPolicySourceCustom, + AbsoluteSessionTimeout: &timeout, + AbsoluteSessionTimeoutUnit: scalekit.TimeUnitMinutes, + IdleSessionTimeoutEnabled: &idleEnabled, + IdleSessionTimeout: &idleTimeout, + IdleSessionTimeoutUnit: scalekit.TimeUnitMinutes, + }) + if err != nil { + log.Fatal(err) + } + + fmt.Println("Policy updated:", updated.PolicySource) + ``` + + + + + ```java title="Set custom session policy" + import com.google.protobuf.Int32Value; + import com.google.protobuf.BoolValue; + import com.scalekit.grpc.scalekit.v1.commons.TimeUnit; + import com.scalekit.grpc.scalekit.v1.organizations.OrganizationSessionPolicySettings; + import com.scalekit.grpc.scalekit.v1.organizations.SessionPolicyType; + + try { + OrganizationSessionPolicySettings policy = OrganizationSessionPolicySettings.newBuilder() + .setPolicySource(SessionPolicyType.CUSTOM) + .setAbsoluteSessionTimeout(Int32Value.of(480)) + .setAbsoluteSessionTimeoutUnit(TimeUnit.MINUTES) + .setIdleSessionTimeoutEnabled(BoolValue.of(true)) + .setIdleSessionTimeout(Int32Value.of(60)) + .setIdleSessionTimeoutUnit(TimeUnit.MINUTES) + .build(); + + OrganizationSessionPolicySettings updated = + scalekitClient.organizations().updateOrganizationSessionPolicy("org_12345", policy); + + System.out.println("Policy updated: " + updated.getPolicySource()); + } catch (Exception e) { + System.err.println("Failed to update session policy: " + e.getMessage()); + } + ``` + + + + +3. **Revert to application defaults** + + Remove the custom policy and restore the organization to the application-level session settings. + + + + + ```javascript title="Revert to application defaults" + try { + await scalekit.organization.updateOrganizationSessionPolicy('org_12345', { + policySource: 'APPLICATION', + }); + } catch (error) { + console.error('Failed to revert session policy:', error.message); + } + ``` + + + + + ```python title="Revert to application defaults" + from scalekit.v1.organizations.organizations_pb2 import SessionPolicyType + + try: + scalekit_client.organization.update_organization_session_policy( + organization_id='org_12345', + policy_source=SessionPolicyType.APPLICATION, + ) + except Exception as e: + print('Failed to revert session policy:', e) + ``` + + + + + ```go title="Revert to application defaults" + _, err := scalekitClient.Organization().UpdateOrganizationSessionPolicy(ctx, "org_12345", scalekit.OrganizationSessionPolicy{ + PolicySource: scalekit.SessionPolicySourceApplication, + }) + if err != nil { + log.Fatal(err) + } + ``` + + + + + ```java title="Revert to application defaults" + import com.scalekit.grpc.scalekit.v1.organizations.OrganizationSessionPolicySettings; + import com.scalekit.grpc.scalekit.v1.organizations.SessionPolicyType; + + try { + OrganizationSessionPolicySettings policy = OrganizationSessionPolicySettings.newBuilder() + .setPolicySource(SessionPolicyType.APPLICATION) + .build(); + + scalekitClient.organizations().updateOrganizationSessionPolicy("org_12345", policy); + } catch (Exception e) { + System.err.println("Failed to revert session policy: " + e.getMessage()); + } + ``` + + + + + diff --git a/src/content/docs/authenticate/manage-users-orgs/hosted-widgets.mdx b/src/content/docs/authenticate/manage-users-orgs/hosted-widgets.mdx index bf49652cc..78ca7cb1c 100644 --- a/src/content/docs/authenticate/manage-users-orgs/hosted-widgets.mdx +++ b/src/content/docs/authenticate/manage-users-orgs/hosted-widgets.mdx @@ -42,7 +42,7 @@ user_widgets: "User widgets\n- User profile\n- User security" { width: 320 } -org_widgets: "Organization widgets\n- Organization settings\n- Member management\n- SSO configuration\n- SCIM configuration" { +org_widgets: "Organization widgets\n- Organization settings\n- Member management\n- SSO configuration\n- SCIM configuration\n- Session policy" { style.font-size: 20 width: 420 } @@ -141,6 +141,15 @@ Organization widgets let your customers manage their organization's settings, me ![](@/assets/docs/hosted-widgets/org_scim.png) +5. ### Manage session policy + + Your customers can view and configure their organization's session policy — setting custom absolute and idle session timeouts that override your application defaults. Scalekit always enforces the stricter of the two. + + + + ![](@/assets/docs/hosted-widgets/2026-05-21-17-12-14.png) @@ -182,6 +191,8 @@ Hosted Widgets enforce access using **Scalekit permissions**. You can map these | `sk_org_sso_manage` | View and modify SSO configuration for an organization | | `sk_org_scim_read` | View SCIM configuration for an organization | | `sk_org_scim_manage` | View and modify SCIM configuration for an organization | +| `sk_org_session_policy_read` | View session policy for an organization | +| `sk_org_session_policy_manage` | View and manage session policy for an organization |