API & SDK Reference: Complete API endpoints and SDK documentation for Node.js, Python, Go, and Java
---
# DOCUMENT BOUNDARY
---
# User authentication flow
> Learn how Scalekit routes users through authentication based on login method and organization SSO policies.
The user’s authentication journey on the hosted login page can differ based on the **login method** they choose and the **organization policies** configured in Scalekit. ## Organization policies [Section titled “Organization policies”](#organization-policies) Organizations can enforce Enterprise SSO for their users. An organization must create an enabled [SSO connection](/authenticate/auth-methods/enterprise-sso/) and add [organization domains](/authenticate/manage-users-orgs/organization-domains/). Scalekit uses **Home Realm Discovery (HRD)** to determine whether a user’s email domain matches a configured organization domain. When a match is found, the user is routed to that organization’s SSO identity provider. **Examples** * A user tries to log in as `user@samecorp.com` on the hosted login page. If `samecorp.com` is registered as an organization domain with SSO enabled, the user is redirected to that organization’s IdP to complete authentication. * A user tries to log in with Google as `user@samecorp.com` on the hosted login page. If `samecorp.com` is registered as an organization domain with SSO enabled, the user is redirected to that organization’s IdP after returning from Google. ## Login method–specific behavior [Section titled “Login method–specific behavior”](#login-methodspecific-behavior) Scalekit allows users to choose different login methods on the hosted login page. The timing of organization domain checks differs slightly by method, but the rules remain consistent. ### Social login [Section titled “Social login”](#social-login) * User authenticates with a social IdP (e.g., Google, GitHub). * Scalekit evaluates the user’s email after social auth completes. * Home Realm Discovery (HRD) checks whether the email domain matches an organization domain. * **Domain match:** User is redirected to the organization’s SSO IdP. * **No match:** Authentication completes. This ensures that enterprise users must complete SSO authentication even if they initially choose social login. ### Passkey login [Section titled “Passkey login”](#passkey-login) * User authenticates using a passkey. * Authentication succeeds immediately. * Scalekit performs Home Realm Discovery (HRD) to check the email domain. * **Domain match:** User is redirected to SSO. * **No match:** Authentication completes. Passkeys authenticate the user, but do not override organization SSO policy. ### Email-based login [Section titled “Email-based login”](#email-based-login) * User enters their email address. * Home Realm Discovery (HRD) runs **before authentication** to check the email domain. * **Domain match:** User is redirected to SSO. * **No match:** Scalekit performs OTP or magic link verification, then authentication completes. ### Authentication flow [Section titled “Authentication flow”](#authentication-flow) This diagram shows the different variations of user’s authentication journey on the hosted login page. *** ## Enterprise SSO Trust model [Section titled “Enterprise SSO Trust model”](#enterprise-sso-trust-model) Most enterprise identity providers (IdPs) like Okta or Microsoft Entra do not prove that a user actually controls the email inbox they sign in with. They only assert an email address in the SAML/OIDC token. Because of this, when a user logs in via Enterprise SSO, Scalekit does not automatically treat that SSO connection as a trusted source of email ownership. Since Scalekit cannot be sure that the SSO user truly owns the email address, the user is taken through an email ownership check (magic link or OTP) to prove control of that inbox. After the user successfully verifies their email, that SSO connection is marked as a verified channel for that specific user, and they do not need to verify email ownership again on subsequent logins via the same connection. If you want an Enterprise SSO connection to be treated as a trusted provider for a specific domain, you can assign one or more domains to the organization. Then, for users logging in via that Enterprise SSO connection whose email address matches one of the configured domains, Scalekit skips additional email ownership verification. | SSO trust case | Example | Result | | -------------- | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | | Trusted SSO | Org has added `acmecorp.com` in organization domain. User authenticates as `user@acmecorp.com` with organization SSO. | Email ownership trusted | | Untrusted SSO | Org has added `acmecorp.com` in organization domain and user authenticates as `user@foocorp.com` with organization SSO. | Email ownership not trusted → Additional verification required | *** ## Forcing SSO from your application [Section titled “Forcing SSO from your application”](#forcing-sso-from-your-application) Your app can override Home Realm Discovery (HRD) by passing `organization_id` or `connection_id` in the authentication request ↗ to Scalekit. When you do this: * Scalekit skips HRD and redirects the user directly to the specified SSO IdP. * After SSO authentication completes, Scalekit checks whether the user’s email domain matches one of the organization domains configured on that SSO connection. * **Domain match**: authentication completes. * **No match**: Scalekit requires additional verification (OTP or magic link) before completing authentication. ## IdP‑initiated SSO [Section titled “IdP‑initiated SSO”](#idpinitiated-sso) In IdP‑initiated SSO, authentication starts at the identity provider instead of your application or the hosted login page. After the IdP authenticates the user and redirects to Scalekit, Scalekit evaluates email ownership trust: * If the user’s email domain matches one of the organization domains configured on the SSO connection, authentication completes. * If the email domain does not match, Scalekit requires additional verification (OTP or magic link) before completing authentication. This workflow ensures IdP‑initiated flows follow the same email ownership and trust guarantees as app‑initiated SSO *** ## Account linking [Section titled “Account linking”](#account-linking) ### What happens [Section titled “What happens”](#what-happens) Scalekit maintains a single user record per email address. For example, if a user first authenticates with passwordless login (magic link/OTP) and later uses Google or Enterprise SSO, Scalekit links both identities to the same user record. These identities are stored on the user object for your app to read if needed. This avoids duplicate users when people switch authentication methods. ### Why it is safe [Section titled “Why it is safe”](#why-it-is-safe) Scalekit only treats an SSO IdP as a trusted source of email ownership when: * the authenticated email domain matches one of the organization domains configured on the SSO connection, or * the user has previously proven email ownership via magic link or OTP. Because the organization has proven domain ownership, and/or the user has proven inbox control, emails from that SSO connection are treated as valid. This prevents attackers from linking identities unless email ownership has been verified through trusted mechanisms.
---
# DOCUMENT BOUNDARY
---
# Implement enterprise SSO
> How to implement enterprise SSO for your application
Enterprise single sign-on (SSO) enables users to authenticate using their organization’s identity provider (IdP), such as Okta, Azure AD, or Google Workspace. [After completing the quickstart](/authenticate/fsa/quickstart/), follow this guide to implement SSO for an organization, streamline admin onboarding, enforce login requirements, and validate your configuration. 1. ## Enable SSO for the organization [Section titled “Enable SSO for the organization”](#enable-sso-for-the-organization) When a user signs up for your application, Scalekit automatically creates an organization and assigns an admin role to the user. Provide an option in your user interface to enable SSO for the organization or workspace. Here’s how you can do that with Scalekit. Use the following SDK method to activate SSO for the organization: * Node.js Enable SSO
```javascript
const settings = {
features: [
{
name: 'sso',
enabled: true,
}
],
};
await scalekit.organization.updateOrganizationSettings(
'', // Get this from the idToken or accessToken
settings
);
```
* Python Enable SSO
```python
settings = [
{
"name": "sso",
"enabled": True
}
]
scalekit.organization.update_organization_settings(
organization_id='', # Get this from the idToken or accessToken
settings=settings
)
```
* Java Enable SSO
```java
OrganizationSettingsFeature featureSSO = OrganizationSettingsFeature.newBuilder()
.setName("sso")
.setEnabled(true)
.build();
updatedOrganization = scalekitClient.organizations()
.updateOrganizationSettings(organizationId, List.of(featureSSO));
```
* Go Enable SSO
```go
settings := OrganizationSettings{
Features: []Feature{
{
Name: "sso",
Enabled: true,
},
},
}
organization, err := sc.Organization().UpdateOrganizationSettings(ctx, organizationId, settings)
if err != nil {
// Handle error
}
```
You can also enable this from the [organization settings](/authenticate/fsa/user-management-settings/) in the Scalekit dashboard. 2. ## Enable admin portal for enterprise customer onboarding [Section titled “Enable admin portal for enterprise customer onboarding”](#enable-admin-portal-for-enterprise-customer-onboarding) After SSO is enabled for that organization, provide a method for configuring a SSO connection with the organization’s identity provider. Scalekit offers two primary approaches: * Generate a link to the admin portal from the Scalekit dashboard and share it with organization admins via your usual channels. * Or embed the admin portal in your application in an inline frame so administrators can configure their IdP without leaving your app. [See how to onboard enterprise customers](/sso/guides/onboard-enterprise-customers/) 3. ## Identify and enforce SSO for organization users [Section titled “Identify and enforce SSO for organization users”](#identify-and-enforce-sso-for-organization-users) Administrators typically register [organization-owned domains](/authenticate/manage-users-orgs/organization-domains/) through the admin portal. When a user attempts to sign in with an email address matching a registered domain, they are automatically redirected to their organization’s designated identity provider for authentication. This is also known as **Home Realm Discovery**. **Organization domains** automatically route users to the correct SSO connection based on their email address. When a user signs in with an email domain that matches a registered organization domain, Scalekit redirects them to that organization’s SSO provider and enforces SSO login. For example, if an organization registers `megacorp.org`, any user signing in with an `joe@megacorp.org` email address is redirected to Megacorp’s SSO provider.  Navigate to **Dashboard > Organizations** and select the target organization > **Overview** > **Organization Domains** section to register organization domains. 4. ## Test your SSO integration [Section titled “Test your SSO integration”](#test-your-sso-integration) Scalekit offers a “Test Organization” feature that enables SSO flow validation without requiring test accounts from your customers’ identity providers. To quickly test the integration, enter an email address using the domains `joe@example.com` or `jane@example.org`. This will trigger a redirect to the IdP simulator, which serves as the test organization’s identity provider for authentication. For a comprehensive step-by-step walkthrough, refer to the [Test SSO integration guide](/sso/guides/test-sso/).
---
# DOCUMENT BOUNDARY
---
# Add passkeys login method
> Enable passkey authentication for your users
Passkeys replace passwords with biometric authentication (fingerprint, face recognition) or device PINs. Built on FIDO® standards (WebAuthn and CTAP), passkeys offer superior security by eliminating phishing and credential stuffing vulnerabilities, while also providing a seamless one-tap login experience. Unlike traditional authentication methods, passkeys sync across devices, removing the need for multiple enrollments and providing better recovery options when devices are lost. Your [existing Scalekit integration](/authenticate/fsa/quickstart) already supports passkeys. To implement, enable passkeys in the Scalekit dashboard and leverage Scalekit’s built-in user passkey registration functionality. 1. ## Enable passkeys in the Scalekit dashboard [Section titled “Enable passkeys in the Scalekit dashboard”](#enable-passkeys-in-the-scalekit-dashboard) Go to Scalekit Dashboard > Authentication > Auth methods > Passkeys and click “Enable”  2. ## Manage passkey registration [Section titled “Manage passkey registration”](#manage-passkey-registration) Let users manage passkeys just by redirecting them to Scalekit from your app (usually through a button in your app that says “Manage passkeys”), or building your own UI. #### Using Scalekit UI [Section titled “Using Scalekit UI”](#using-scalekit-ui) To enable users to register and manage their passkeys, redirect them to the Scalekit passkey registration page.  Construct the URL by appending `/ui/profile/passkeys` to your Scalekit environment URL Passkey Registration URL
```js
/ui/profile/passkeys
```
This opens a page where users can: * Register new passkeys * Remove existing passkeys * View their registered passkeys To show the page on your own domain instead of the default Scalekit domain, configure a [branded custom domain](/guides/custom-domain). Users then see a URL such as `https://auth.yourapp.com/ui/profile/passkeys`. #### In your own UI [Section titled “In your own UI”](#in-your-own-ui) If you prefer to create a custom user interface for passkey management, Scalekit offers comprehensive APIs that enable you to build a personalized experience. These APIs allow you to list registered passkeys, rename them, and remove them entirely. However registration of passkeys is only supported through the Scalekit UI. * Node.js List user's passkeys
```js
// : fetch from Access Token or ID Token after identity verification
const res = await fetch(
'/api/v1/webauthn/credentials?user_id=',
{ headers: { Authorization: 'Bearer ' } }
);
const data = await res.json();
console.log(data);
```
Rename a passkey
```js
// : obtained from list response (id of each passkey)
await fetch('/api/v1/webauthn/credentials/', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer '
},
body: JSON.stringify({ display_name: '' })
});
```
Remove a passkey
```js
// : obtained from list response (id of each passkey)
await fetch('/api/v1/webauthn/credentials/', {
method: 'DELETE',
headers: { Authorization: 'Bearer ' }
});
```
* Python List user's passkeys
```python
import requests
# : fetch from access token or ID token after identity verification
r = requests.get(
'/api/v1/webauthn/credentials',
params={'user_id': ''},
headers={'Authorization': 'Bearer '}
)
print(r.json())
```
Rename a passkey
```python
import requests
# : obtained from list response (id of each passkey)
requests.patch(
'/api/v1/webauthn/credentials/',
json={'display_name': ''},
headers={'Authorization': 'Bearer '}
)
```
Remove a passkey
```python
import requests
# : obtained from list response (id of each passkey)
requests.delete(
'/api/v1/webauthn/credentials/',
headers={'Authorization': 'Bearer '}
)
```
* Java List user's passkeys
```java
var client = java.net.http.HttpClient.newHttpClient();
// : fetch from Access Token or ID Token after identity verification
var req = java.net.http.HttpRequest.newBuilder(
java.net.URI.create("/api/v1/webauthn/credentials?user_id=")
)
.header("Authorization", "Bearer ")
.GET().build();
var res = client.send(req, java.net.http.HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
```
Rename a passkey
```java
var client = java.net.http.HttpClient.newHttpClient();
var body = "{\"display_name\":\"\"}";
// : obtained from list response (id of each passkey)
var req = java.net.http.HttpRequest.newBuilder(
java.net.URI.create("/api/v1/webauthn/credentials/")
)
.header("Authorization", "Bearer ")
.header("Content-Type","application/json")
.method("PATCH", java.net.http.HttpRequest.BodyPublishers.ofString(body))
.build();
client.send(req, java.net.http.HttpResponse.BodyHandlers.discarding());
```
Remove a passkey
```java
var client = java.net.http.HttpClient.newHttpClient();
// : obtained from list response (id of each passkey)
var req = java.net.http.HttpRequest.newBuilder(
java.net.URI.create("/api/v1/webauthn/credentials/")
)
.header("Authorization", "Bearer ")
.DELETE().build();
client.send(req, java.net.http.HttpResponse.BodyHandlers.discarding());
```
* Go List user's passkeys
```go
// imports: net/http, io, fmt
// : fetch from access token or ID token after identity verification
req, _ := http.NewRequest("GET", "/api/v1/webauthn/credentials?user_id=", nil)
req.Header.Set("Authorization", "Bearer ")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body)
fmt.Println(string(b))
```
Rename a passkey
```go
// imports: net/http, bytes
payload := bytes.NewBufferString(`{"display_name":""}`)
// : obtained from list response (id of each passkey)
req, _ := http.NewRequest("PATCH", "/api/v1/webauthn/credentials/", payload)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer ")
http.DefaultClient.Do(req)
```
Remove a passkey
```go
// imports: net/http
// : obtained from list response (id of each passkey)
req, _ := http.NewRequest("DELETE", "/api/v1/webauthn/credentials/", nil)
req.Header.Set("Authorization", "Bearer ")
http.DefaultClient.Do(req)
```
3. ## Users can log in with passkeys [Section titled “Users can log in with passkeys”](#users-can-log-in-with-passkeys) Users who have registered passkeys can log in with them. This time when login page shows, users can select “Passkey” as the authentication method.  During sign-up, you’ll continue to use established authentication methods like [verification codes, magic links](/authenticate/auth-methods/passwordless/) or [social logins](/authenticate/auth-methods/social-logins/). Once a user is registered, they can then add passkeys as an additional, convenient login option.
---
# DOCUMENT BOUNDARY
---
# Sign in with magic link or Email OTP
> Enable passwordless sign-in with email verification codes or magic links
Configure Magic Link & OTP to enable passwordless authentication for your application. After completing the [quickstart guide](/authenticate/fsa/quickstart/), set up email verification codes or magic links so users can sign in without passwords. Switch between those passwordless methods without modifying any code: | Method | How it works | Best for | | ------------------------------ | ---------------------------------------------------------------- | -------------------------------------------- | | Verification code | Users receive a one-time code via email and enter it in your app | Applications requiring explicit verification | | Magic link | Users click a link in their email to authenticate | Quick, frictionless sign-in | | Magic link + Verification code | Users choose either method | Maximum flexibility and user choice | ## Configure magic link or OTP [Section titled “Configure magic link or OTP”](#configure-magic-link-or-otp) In the Scalekit dashboard, go to **Authentication > Auth methods > Magic Link & OTP**  1. ### Select authentication method [Section titled “Select authentication method”](#select-authentication-method) Choose one of three methods: * **Verification code** - Users enter a 6-digit code sent to their email * **Magic link** - Users click a link in their email to authenticate * **Magic link + Verification code** - Users can choose either method 2. ### Set expiry period [Section titled “Set expiry period”](#set-expiry-period) Configure how long verification codes and magic links remain valid: * **Default**: 300 seconds (5 minutes) * **Range**: 60 to 3600 seconds * **Recommendation**: 300 seconds balances security and usability ## Enforce same browser origin [Section titled “Enforce same browser origin”](#enforce-same-browser-origin) When enforcing same browser origin, users are required to complete magic link authentication within the same browser where they initiated the login process. This security feature is particularly recommended for applications dealing with sensitive data or financial transactions, as it adds an extra layer of protection against potential unauthorized access attempts. **Example scenario**: A healthcare app where a user requests a magic link on their laptop. If someone intercepts the email and tries to open it on a different device, the authentication fails. ## Regenerate credentials on resend [Section titled “Regenerate credentials on resend”](#regenerate-credentials-on-resend) When a user requests a new Magic Link or Email OTP, the system generates a fresh code or link while automatically invalidating the previous one. This approach is recommended for all applications as a critical security measure to prevent potential misuse of compromised credentials. **Example scenario**: A user requests a verification code but doesn’t receive it. They request a new code. With this setting enabled, the first code becomes invalid, preventing unauthorized access if the original email was intercepted.
---
# DOCUMENT BOUNDARY
---
# Add social login to your app
> Implement authentication with Google, Microsoft, GitHub, and other social providers
First, complete the [quickstart guide](/authenticate/fsa/quickstart/) to integrate Scalekit auth into your application. Scalekit natively supports OAuth 2.0, enabling you to easily configure social login providers that will automatically appear as authentication options on your login page. 1. ## Configure social login providers [Section titled “Configure social login providers”](#configure-social-login-providers) Google login is pre-configured in all development environments for simplified testing. You can integrate additional social login providers by setting up your own connection credentials with each provider. Navigate to **Authentication** > **Auth Methods** > **Social logins** in your dashboard to configure these settings ### Google Enable users to sign in with their Google accounts using OAuth 2.0 [Setup →](/guides/integrations/social-connections/google) ### GitHub Allow users to authenticate using their GitHub credentials [Setup →](/guides/integrations/social-connections/github) ### Microsoft Integrate Microsoft accounts for seamless user authentication [Setup →](/guides/integrations/social-connections/microsoft) ### GitLab Enable GitLab-based authentication for your application [Setup →](/guides/integrations/social-connections/gitlab) ### LinkedIn Let users sign in with their LinkedIn accounts using OAuth 2.0 [Setup →](/guides/integrations/social-connections/linkedin) ### Salesforce Enable Salesforce-based authentication for your application [Setup →](/guides/integrations/social-connections/salesforce) 2. ## Test the social connection [Section titled “Test the social connection”](#test-the-social-connection) After configuration, test the social connection by clicking on “Test Connection” in the dashboard. You will be redirected to the provider’s consent screen to authorize access. A summary table will show the information that will be sent to your app.  ## Access social login options on your login page [Section titled “Access social login options on your login page”](#access-social-login-options-on-your-login-page) Your application now supports social logins. Begin the [login process](/authenticate/fsa/implement-login/) to experience the available social login options. Users can authenticate using providers like Google, GitHub, Microsoft, and any others you have set up.
---
# DOCUMENT BOUNDARY
---
# SDKs
> Ready-to-use SDKs for Node.js, Python, Go, and Java to integrate Scalekit into your app
* [Node.jsv2.15.0](/saaskit/sdks/node/) [npm install @scalekit-sdk/node](/saaskit/sdks/node/) [Full-featured, TypeScript-friendly SDK for modern Node.js based applications](/saaskit/sdks/node/) [Updated 1 day agoInstall→](/saaskit/sdks/node/) * [Expressv2.15.0](/saaskit/sdks/express/) [npm install @scalekit-sdk/node express](/saaskit/sdks/express/) [Session middleware for Express. Hosted login, encrypted cookie, token refresh.](/saaskit/sdks/express/) [Updated 1 day agoInstall→](/saaskit/sdks/express/) * [Next.jsv2.15.0](/saaskit/sdks/nextjs/) [npm install @scalekit-sdk/node](/saaskit/sdks/nextjs/) [Session middleware for the Next.js App Router, including Edge Runtime.](/saaskit/sdks/nextjs/) [Updated 1 day agoInstall→](/saaskit/sdks/nextjs/) * [Pythonv2.19.1](/saaskit/sdks/python/) [pip install scalekit-sdk-python](/saaskit/sdks/python/) [Async-first design with complete type hints and Pydantic validation](/saaskit/sdks/python/) [Updated 1 day agoInstall→](/saaskit/sdks/python/) * [Flaskv2.19.1](/saaskit/sdks/flask/) [pip install "scalekit-sdk-python\[flask\]"](/saaskit/sdks/flask/) [Session middleware for Flask. Hosted login, encrypted cookie, token refresh.](/saaskit/sdks/flask/) [Updated 1 day agoInstall→](/saaskit/sdks/flask/) * [FastAPIv2.19.1](/saaskit/sdks/fastapi/) [pip install "scalekit-sdk-python\[fastapi\]"](/saaskit/sdks/fastapi/) [Session middleware for FastAPI. Protect routes with Depends().](/saaskit/sdks/fastapi/) [Updated 1 day agoInstall→](/saaskit/sdks/fastapi/) * [Djangov2.19.1](/saaskit/sdks/django/) [pip install "scalekit-sdk-python\[django\]"](/saaskit/sdks/django/) [Session middleware for Django. Settings-based config and login\_required.](/saaskit/sdks/django/) [Updated 1 day agoInstall→](/saaskit/sdks/django/) * [Gov2.8.0](/saaskit/sdks/go/) [go get github.com/scalekit-inc/scalekit-sdk-go](/saaskit/sdks/go/) [Zero-dependency, idiomatic Go SDK for high-performance services](/saaskit/sdks/go/) [Updated 1 month agoInstall→](/saaskit/sdks/go/) * [Javav2.4.0](/saaskit/sdks/java/) [Maven Central: com.scalekit:scalekit-sdk-java](/saaskit/sdks/java/) [Enterprise-ready SDK with seamless Spring Boot integration](/saaskit/sdks/java/) [Updated 1 day agoInstall→](/saaskit/sdks/java/) * [Expo](/sdks/expo/) [npx expo install @scalekit-sdk/expo](/sdks/expo/) [Official Expo SDK with React Hooks for enterprise-ready mobile authentication](/sdks/expo/) [Install→](/sdks/expo/) * [iOS](/sdks/ios/) [Swift Package Manager: ScalekitSDK](/sdks/ios/) [Native iOS SDK for enterprise-ready mobile authentication via AppAuth](/sdks/ios/) [Install→](/sdks/ios/)
---
# DOCUMENT BOUNDARY
---
# Authenticate with Scalekit API
> Learn how to authenticate your server applications with Scalekit API using OAuth 2.0 Client Credentials flow
This guide explains how to authenticate your server applications with the Scalekit API using the OAuth 2.0 Client Credentials flow. After reading this guide, you’ll be able to: * Generate an access token using your API credentials * Make authenticated API requests to Scalekit endpoints * Handle authentication errors appropriately This guide targets developers who need to integrate Scalekit services into their backend applications or automate tasks through API calls. ## Before you begin [Section titled “Before you begin”](#before-you-begin) Before starting the authentication process, ensure you have set up your Scalekit account and obtained your API credentials. ## Step 1: Configure your environment [Section titled “Step 1: Configure your environment”](#step-1-configure-your-environment) Store your API credentials securely as environment variables: Environment variables
```sh
1
SCALEKIT_ENVIRONMENT_URL=""
2
SCALEKIT_CLIENT_ID=""
3
SCALEKIT_CLIENT_SECRET=""
```
## Step 2: Request an access token [Section titled “Step 2: Request an access token”](#step-2-request-an-access-token) To authenticate your API requests, you must first obtain an access token from the Scalekit authorization server. ### Token endpoint URL [Section titled “Token endpoint URL”](#token-endpoint-url) Token endpoint URL
```sh
1
https:///oauth/token
```
### Send a token request [Section titled “Send a token request”](#send-a-token-request) Choose your preferred method to request an access token: * cURL
```bash
1
curl -X POST \
2
"https:///oauth/token" \
3
-H "Content-Type: application/x-www-form-urlencoded" \
4
-d "grant_type=client_credentials" \
5
-d "client_id=" \
6
-d "client_secret=" \
7
-d "scope=openid profile email"
```
* Node.js
```javascript
1
import axios from 'axios';
2
3
const config = {
4
clientId: process.env.SCALEKIT_CLIENT_ID,
5
clientSecret: process.env.SCALEKIT_CLIENT_SECRET,
6
tokenUrl: `${process.env.SCALEKIT_ENVIRONMENT_URL}/oauth/token`,
7
scope: 'openid email profile',
8
};
9
10
async function getClientCredentialsToken() {
11
try {
12
const params = new URLSearchParams();
13
params.append('grant_type', 'client_credentials');
14
params.append('client_id', config.clientId);
15
params.append('client_secret', config.clientSecret);
16
17
if (config.scope) {
18
params.append('scope', config.scope);
19
}
20
21
const response = await axios.post(config.tokenUrl, params, {
22
headers: {
23
'Content-Type': 'application/x-www-form-urlencoded',
24
},
25
});
26
27
const { access_token, expires_in } = response.data;
28
console.log(`Token acquired successfully. Expires in ${expires_in} seconds.`);
29
return access_token;
30
} catch (error) {
31
console.error('Error getting client credentials token:', error);
32
throw new Error('Failed to obtain access token');
33
}
34
}
```
* Python
```python
1
import os
2
import json
3
import requests
4
5
def get_access_token():
6
"""Request an access token using client credentials."""
7
headers = {"Content-Type": "application/x-www-form-urlencoded"}
8
params = {
9
"grant_type": "client_credentials",
10
"client_id": os.environ['SCALEKIT_CLIENT_ID'],
11
"client_secret": os.environ['SCALEKIT_CLIENT_SECRET']
12
}
13
oauth_token_url = os.environ['SCALEKIT_ENVIRONMENT_URL']
14
15
response = requests.post(oauth_token_url, headers=headers, data=params, verify=True)
16
access_token = response.json().get('access_token')
17
return access_token
```
### Understand the token response [Section titled “Understand the token response”](#understand-the-token-response) When your request succeeds, the server returns a JSON response with the following fields: | Field | Description | | -------------- | ----------------------------------------------------- | | `access_token` | The token you’ll use to authenticate API requests | | `token_type` | The token type (always Bearer for this flow) | | `expires_in` | Token validity period in seconds (typically 24 hours) | | `scope` | The authorized scopes for this token | Example token response: Token response
```json
1
{
2
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InNua181Ok4OTEyMjU2NiIsInR5cCI6IkpXVCJ9...",
3
"token_type": "Bearer",
4
"expires_in": 86399,
5
"scope": "openid"
6
}
```
## Step 3: Make authenticated API requests [Section titled “Step 3: Make authenticated API requests”](#step-3-make-authenticated-api-requests) After obtaining an access token, add it to the `Authorization` header in your API requests. * cURL
```bash
1
curl --request GET "https:///api/v1/organizations" \
2
-H "Content-Type: application/json" \
3
-H "Authorization: Bearer "
```
* Node.js (axios)
```javascript
1
async function makeAuthenticatedRequest(endpoint) {
2
try {
3
const access_token = await getClientCredentialsToken();
4
const url = `${process.env.SCALEKIT_ENVIRONMENT_URL}${endpoint}`;
5
6
const response = await axios.get(url, {
7
headers: {
8
Authorization: `Bearer ${access_token}`,
9
},
10
});
11
12
console.log('API Response:', response.data);
13
return response.data;
14
} catch (error) {
15
console.error('Error making authenticated request:', error);
16
throw error;
17
}
18
}
```
* Python (requests)
```python
1
import os
2
import json
3
import requests
4
5
env_url = os.environ['SCALEKIT_ENVIRONMENT_URL']
6
7
def get_access_token():
8
"""Request an access token using client credentials."""
9
headers = {"Content-Type": "application/x-www-form-urlencoded"}
10
params = {
11
"grant_type": "client_credentials",
12
"client_id": os.environ['SCALEKIT_CLIENT_ID'],
13
"client_secret": os.environ['SCALEKIT_CLIENT_SECRET']
14
}
15
16
response = requests.post(
17
url=f"{env_url}/oauth/token",
18
headers=headers,
19
data=params,
20
verify=True)
21
22
access_token = response.json().get('access_token')
23
return access_token
24
25
def get_organizations(get_orgs_endpoint):
26
"""Retrieve all organizations for the specified environment."""
27
access_token = get_access_token()
28
headers = {"Authorization": f"Bearer {access_token}"}
29
30
response = requests.get(
31
url=f"{env_url}/{get_orgs_endpoint}",
32
headers=headers)
33
return response
```
Example API response
```json
1
{
2
"next_page_token": "",
3
"total_size": 3,
4
"organizations": [
5
{
6
"id": "org_64444217115541813",
7
"create_time": "2025-03-20T13:55:46.690Z",
8
"update_time": "2025-03-21T05:55:03.416772Z",
9
"display_name": "Looney Corp",
10
"region_code": "US",
11
"external_id": "my_unique_id",
12
"metadata": {}
13
}
14
],
15
"prev_page_token": ""
16
}
```
## Common authentication issues [Section titled “Common authentication issues”](#common-authentication-issues) | Issue | Possible cause | Solution | | ---------------- | ------------------------ | ------------------------------- | | 401 Unauthorized | Invalid or expired token | Generate a new access token | | 403 Forbidden | Insufficient permissions | Check client credentials scopes | | Connection error | Network or server issue | Retry with exponential backoff | ## Next steps [Section titled “Next steps”](#next-steps) Now that you can authenticate with the Scalekit API, you can: * Browse the complete API reference to discover available endpoints * Create a token management service to handle token refreshing * Implement error handling strategies for production use
---
# DOCUMENT BOUNDARY
---
# UI events from the embedded admin portal
> Learn how to listen for and handle UI events from the embedded admin portal, such as SSO connection status and session expiration.
The embedded admin portal emits browser events that allow your application to respond to configuration changes made by organization admins. Use these events to provide real-time feedback, update your UI, sync configuration state, or trigger workflows in your application. Common use cases include displaying success notifications when SSO is configured, refreshing authentication settings after directory sync is enabled, or prompting users to re-authenticate when their admin portal session expires. ## Listening to admin portal events [Section titled “Listening to admin portal events”](#listening-to-admin-portal-events) Add an event listener to your parent window to receive events from the embedded admin portal iframe:
```js
1
window.addEventListener('message', (event) => {
2
// Security: Always validate the event origin matches your Scalekit environment
3
if (event.origin !== 'https://your-env.scalekit.com') {
4
return; // Ignore events from untrusted sources
5
}
6
7
// Check if this is a valid admin portal event
8
if (event.data && event.data.event_type) {
9
const { event_type, organization_id, data } = event.data;
10
11
// Handle specific event types
12
switch (event_type) {
13
case 'ORGANIZATION_SSO_ENABLED':
14
// Show success notification, refresh SSO settings, etc.
15
showNotification('SSO enabled successfully');
16
break;
17
18
case 'PORTAL_SESSION_EXPIRY':
19
// Prompt user to refresh the admin portal
20
promptSessionRefresh();
21
break;
22
23
default:
24
console.log('Received event:', event.data);
25
}
26
}
27
});
```
Security requirement The domain of your parent window must be listed in **Dashboard > API Config > Redirect URIs** for the admin portal to emit events. Always validate `event.origin` to ensure events come from your trusted Scalekit environment URL. *** ## SSO events [Section titled “SSO events”](#sso-events) ### `ORGANIZATION_SSO_ENABLED` [Section titled “ORGANIZATION\_SSO\_ENABLED”](#organization_sso_enabled) Fires when an organization admin successfully enables a Single Sign-On connection in the admin portal. ORGANIZATION\_SSO\_ENABLED
```json
1
{
2
"event_type": "ORGANIZATION_SSO_ENABLED",
3
"object": "connection",
4
"organization_id": "org_4010340X34236531", // Organization that enabled SSO
5
"message": "Single sign-on connection enabled successfully",
6
"data": {
7
"connection_type": "SSO",
8
"id": "conn_4256075523X312", // Connection ID for API calls
9
"type": "OIDC", // Protocol: OIDC or SAML
10
"provider": "OKTA", // Identity provider configured
11
"enabled": true
12
}
13
}
```
| Field | Type | Description | | ---------------------- | ------- | ------------------------------------------- | | `event_type` | string | The type of event being triggered | | `object` | string | The object type associated with the event | | `organization_id` | string | Unique identifier for the organization | | `message` | string | Human-readable message describing the event | | `data.connection_type` | string | Type of connection (SSO) | | `data.id` | string | Unique identifier for the connection | | `data.type` | string | Protocol type (e.g., OIDC, SAML) | | `data.provider` | string | Identity provider name | | `data.enabled` | boolean | Indicates if the connection is enabled | ### `ORGANIZATION_SSO_DISABLED` [Section titled “ORGANIZATION\_SSO\_DISABLED”](#organization_sso_disabled) Fires when an organization admin disables their Single Sign-On connection in the admin portal. ORGANIZATION\_SSO\_DISABLED
```json
1
{
2
"event_type": "ORGANIZATION_SSO_DISABLED",
3
"object": "connection",
4
"organization_id": "org_4010340X34236531", // Organization that disabled SSO
5
"message": "Single sign-on connection disabled successfully",
6
"data": {
7
"connection_type": "SSO",
8
"id": "conn_4256075523X312", // Connection ID that was disabled
9
"type": "OIDC", // Protocol: OIDC or SAML
10
"provider": "OKTA", // Identity provider that was configured
11
"enabled": false
12
}
13
}
```
| Field | Type | Description | | ---------------------- | ------- | ------------------------------------------- | | `event_type` | string | The type of event being triggered | | `object` | string | The object type associated with the event | | `organization_id` | string | Unique identifier for the organization | | `message` | string | Human-readable message describing the event | | `data.connection_type` | string | Type of connection (SSO) | | `data.id` | string | Unique identifier for the connection | | `data.type` | string | Protocol type (e.g., OIDC, SAML) | | `data.provider` | string | Identity provider name | | `data.enabled` | boolean | Indicates if the connection is enabled | ## Session events [Section titled “Session events”](#session-events) ### `PORTAL_LOAD_SUCCESS` [Section titled “PORTAL\_LOAD\_SUCCESS”](#portal_load_success) Fires when the admin portal session is created and loaded successfully. Use this event to display the portal iframe and confirm readiness to users. PORTAL\_LOAD\_SUCCESS
```json
1
{
2
"event_type": "PORTAL_LOAD_SUCCESS",
3
"object": "session",
4
"message": "The admin portal loaded successfully",
5
"organization_id": "org_43982563588440584",
6
"data": {
7
"expiry": "2025-02-28T12:40:35.911Z" // ISO 8601 timestamp when session expires
8
}
9
}
```
| Field | Type | Description | | ----------------- | ------ | ---------------------------------------------------------- | | `event_type` | string | The type of event being triggered | | `object` | string | The object type associated with the event | | `organization_id` | string | Unique identifier for the organization | | `message` | string | Human-readable message describing the event | | `data.expiry` | string | ISO 8601 timestamp indicating when the session will expire | ### `PORTAL_LOAD_FAILURE` [Section titled “PORTAL\_LOAD\_FAILURE”](#portal_load_failure) Fires when the admin portal session failed to load. Use this to prompt users that the session has failed to load. PORTAL\_LOAD\_FAILURE
```json
1
{
2
"event_type": "PORTAL_LOAD_FAILURE",
3
"object": "session",
4
"message": "The admin portal failed to load",
5
"data": {
6
"error_code": "SESSION_EXPIRED" // error code indicating why the session load failed
7
}
8
}
```
| Field | Type | Description | | ----------------- | ------ | ------------------------------------------------- | | `event_type` | string | The type of event being triggered | | `object` | string | The object type associated with the event | | `message` | string | Human-readable message describing the event | | `data.error_code` | string | Error code indicating why the session load failed | ### `PORTAL_SESSION_WARNING` [Section titled “PORTAL\_SESSION\_WARNING”](#portal_session_warning) Fires when the admin portal session is about to expire (typically 5 minutes before expiration). Use this to prompt users to save their work or refresh their session. PORTAL\_SESSION\_WARNING
```json
1
{
2
"event_type": "PORTAL_SESSION_WARNING",
3
"object": "session",
4
"message": "The admin portal session will expire in 5 minutes",
5
"organization_id": "org_43982563588440584",
6
"data": {
7
"expiry": "2025-02-28T12:40:35.911Z" // ISO 8601 timestamp when session expires
8
}
9
}
```
| Field | Type | Description | | ----------------- | ------ | ---------------------------------------------------------- | | `event_type` | string | The type of event being triggered | | `object` | string | The object type associated with the event | | `organization_id` | string | Unique identifier for the organization | | `message` | string | Human-readable message describing the event | | `data.expiry` | string | ISO 8601 timestamp indicating when the session will expire | ### `PORTAL_SESSION_EXPIRY` [Section titled “PORTAL\_SESSION\_EXPIRY”](#portal_session_expiry) Fires when the admin portal session has expired. Use this to hide the admin portal iframe and prompt users to re-authenticate. PORTAL\_SESSION\_EXPIRY
```json
1
{
2
"event_type": "PORTAL_SESSION_EXPIRY",
3
"object": "session",
4
"message": "The admin portal session has expired",
5
"organization_id": "org_43982563588440584",
6
"data": {
7
"expiry": "2025-02-28T12:40:35.911Z" // ISO 8601 timestamp when session expired
8
}
9
}
```
| Field | Type | Description | | ----------------- | ------ | ------------------------------------------------------ | | `event_type` | string | The type of event being triggered | | `object` | string | The object type associated with the event | | `organization_id` | string | Unique identifier for the organization | | `message` | string | Human-readable message describing the event | | `data.expiry` | string | ISO 8601 timestamp indicating when the session expired | ## Directory events [Section titled “Directory events”](#directory-events) ### `ORGANIZATION_DIRECTORY_ENABLED` [Section titled “ORGANIZATION\_DIRECTORY\_ENABLED”](#organization_directory_enabled) Fires when an organization admin successfully configures and enables SCIM directory provisioning in the admin portal. ORGANIZATION\_DIRECTORY\_ENABLED
```json
1
{
2
"event_type": "ORGANIZATION_DIRECTORY_ENABLED",
3
"object": "directory",
4
"organization_id": "org_45716217859670289", // Organization that enabled directory sync
5
"message": "SCIM Provisioning enabled successfully",
6
"data": {
7
"directory_type": "SCIM", // Directory protocol type
8
"id": "dir_45716228982964495", // Directory connection ID for API calls
9
"provider": "MICROSOFT_AD", // Identity provider: OKTA, AZURE_AD, GOOGLE, etc.
10
"enabled": true
11
}
12
}
```
| Field | Type | Description | | --------------------- | ------- | ---------------------------------------------- | | `event_type` | string | The type of event being triggered | | `object` | string | The object type associated with the event | | `organization_id` | string | Unique identifier for the organization | | `message` | string | Human-readable message describing the event | | `data.directory_type` | string | Type of directory synchronization (SCIM) | | `data.id` | string | Unique identifier for the directory connection | | `data.provider` | string | Identity provider name | | `data.enabled` | boolean | Indicates if the directory sync is enabled | ### `ORGANIZATION_DIRECTORY_DISABLED` [Section titled “ORGANIZATION\_DIRECTORY\_DISABLED”](#organization_directory_disabled) Fires when an organization admin disables SCIM directory provisioning in the admin portal. ORGANIZATION\_DIRECTORY\_DISABLED
```json
1
{
2
"event_type": "ORGANIZATION_DIRECTORY_DISABLED",
3
"object": "directory",
4
"organization_id": "org_45716217859670289", // Organization that disabled directory sync
5
"message": "SCIM Provisioning disabled successfully",
6
"data": {
7
"directory_type": "SCIM", // Directory protocol type
8
"id": "dir_45716228982964495", // Directory connection ID that was disabled
9
"provider": "MICROSOFT_AD", // Identity provider that was configured
10
"enabled": false
11
}
12
}
```
| Field | Type | Description | | --------------------- | ------- | ---------------------------------------------- | | `event_type` | string | The type of event being triggered | | `object` | string | The object type associated with the event | | `organization_id` | string | Unique identifier for the organization | | `message` | string | Human-readable message describing the event | | `data.directory_type` | string | Type of directory synchronization (SCIM) | | `data.id` | string | Unique identifier for the directory connection | | `data.provider` | string | Identity provider name | | `data.enabled` | boolean | Indicates if the directory sync is enabled | ## Complete event handler Example [Section titled “Complete event handler ”](#complete-event-handler-) Here’s a complete example showing how to handle all admin portal events in a production application: Complete admin portal event handler
```js
1
// Initialize event handling for the admin portal
2
function initAdminPortalEventHandling(scalekitEnvironmentUrl) {
3
window.addEventListener('message', (event) => {
4
// Security: Validate event origin
5
if (event.origin !== scalekitEnvironmentUrl) {
6
return;
7
}
8
9
if (!event.data || !event.data.event_type) {
10
return;
11
}
12
13
const { event_type, organization_id, data, message } = event.data;
14
15
// Log all events for debugging
16
console.log('[Admin Portal Event]', { event_type, organization_id, data });
17
18
switch (event_type) {
19
case 'ORGANIZATION_SSO_ENABLED':
20
handleSSOEnabled(organization_id, data);
21
break;
22
23
case 'ORGANIZATION_SSO_DISABLED':
24
handleSSODisabled(organization_id, data);
25
break;
26
27
case 'ORGANIZATION_DIRECTORY_ENABLED':
28
handleDirectoryEnabled(organization_id, data);
29
break;
30
31
case 'ORGANIZATION_DIRECTORY_DISABLED':
32
handleDirectoryDisabled(organization_id, data);
33
break;
34
35
case 'PORTAL_LOAD_SUCCESS':
36
handlePortalLoadSuccess(data.expiry);
37
break;
38
39
case 'PORTAL_LOAD_FAILURE':
40
handlePortalLoadFailure(data.error_code);
41
break;
42
43
case 'PORTAL_SESSION_WARNING':
44
handleSessionWarning(data.expiry);
45
break;
46
47
case 'PORTAL_SESSION_EXPIRY':
48
handleSessionExpiry();
49
break;
50
51
default:
52
console.warn('Unknown event type:', event_type);
53
}
54
});
55
}
56
57
function handleSSOEnabled(orgId, data) {
58
// Show success notification
59
showToast('success', `SSO enabled successfully with ${data.provider}`);
60
61
// Sync configuration to your backend
62
fetch('/api/organizations/${orgId}/sync-sso', {
63
method: 'POST',
64
headers: { 'Content-Type': 'application/json' },
65
body: JSON.stringify({ connectionId: data.id, provider: data.provider })
66
});
67
68
// Update UI to reflect SSO is active
69
updateOrganizationUI(orgId, { ssoEnabled: true });
70
}
71
72
function handlePortalLoadSuccess(expiryTime) {
73
const expiryDate = new Date(expiryTime);
74
console.log('[Admin Portal] Loaded successfully, session expires at', expiryDate);
75
76
// Update UI to show the portal is ready
77
document.getElementById('admin-portal-iframe').style.display = 'block';
78
}
79
80
function handlePortalLoadFailure(errorCode) {
81
console.error('[Admin Portal] Failed to load, error code:', errorCode);
82
83
// Hide the iframe and show an error message to the user
84
document.getElementById('admin-portal-iframe').style.display = 'none';
85
86
showModal({
87
title: 'Portal failed to load',
88
message: errorCode === 'SESSION_EXPIRED'
89
? 'Your session has expired. Please refresh to continue.'
90
: `The admin portal could not be loaded (${errorCode}). Please try again.`,
91
action: {
92
label: 'Refresh Page',
93
onClick: () => window.location.reload()
94
}
95
});
96
}
97
98
function handleSessionWarning(expiryTime) {
99
const expiryDate = new Date(expiryTime);
100
const minutesLeft = Math.round((expiryDate - new Date()) / 60000);
101
102
showNotification({
103
type: 'warning',
104
message: `Your admin session will expire in ${minutesLeft} minutes`,
105
action: {
106
label: 'Refresh Session',
107
onClick: () => window.location.reload()
108
}
109
});
110
}
111
112
function handleSessionExpiry() {
113
// Hide the admin portal iframe
114
document.getElementById('admin-portal-iframe').style.display = 'none';
115
116
// Show message to user
117
showModal({
118
title: 'Session Expired',
119
message: 'Your admin portal session has expired. Please refresh to continue.',
120
action: {
121
label: 'Refresh Page',
122
onClick: () => window.location.reload()
123
}
124
});
125
}
126
127
// Initialize when your app loads
128
initAdminPortalEventHandling('https://your-env.scalekit.com');
```
---
# DOCUMENT BOUNDARY
---
# BigQuery (Service Account)
Connect to BigQuery using a GCP service account for server-to-server authentication without user login.  Supports authentication: Service Account ## Create a Connection [Section titled “Create a Connection”](#create-a-connection) In [Scalekit dashboard](https://app.scalekit.com), go to **AgentKit** > **Connections** > **Create Connection**. Find **BigQuery (Service Account)** and click **Create**. That’s it — no OAuth credentials or redirect URIs needed. BigQuery Service Account uses server-to-server authentication handled entirely through your GCP service account credentials. ## Create a Connected Account [Section titled “Create a Connected Account”](#create-a-connected-account) To connect a BigQuery account programmatically, you need a GCP service account JSON key. Here’s how to get one: 1. ### Create a GCP service account * Go to [Google Cloud Console](https://console.cloud.google.com) → **IAM & Admin** → **Service Accounts**. * Click **+ Create Service Account**, enter a name and description, and click **Create and Continue**. * Grant the service account the **BigQuery Data Viewer**, **BigQuery Data Editor**, and **BigQuery Job User** roles, then click **Done**. 2. ### Enable the BigQuery API * In [Google Cloud Console](https://console.cloud.google.com), go to **APIs & Services** → **Library**. * Search for **BigQuery API** and click **Enable**.  3. ### Download the service account JSON key * In the Service Accounts list, click on your service account. * Go to the **Keys** tab → **Add Key** → **Create new key**. * Select **JSON** and click **Create**. The key file downloads automatically. * Use the contents of this file as the `service_account_json` value when creating a connected account. ## Usage [Section titled “Usage”](#usage) ## Tool list [Section titled “Tool list”](#tool-list) ## `bigqueryserviceaccount_get_dataset` [Section titled “bigqueryserviceaccount\_get\_dataset”](#bigqueryserviceaccount_get_dataset) Retrieve metadata for a specific BigQuery dataset, including location, description, labels, access controls, and creation/modification times. | Name | Type | Required | Description | | ------------ | ------ | -------- | --------------------------------- | | `dataset_id` | string | Yes | The ID of the dataset to retrieve | ## `bigqueryserviceaccount_get_job` [Section titled “bigqueryserviceaccount\_get\_job”](#bigqueryserviceaccount_get_job) Retrieve the status and configuration of a BigQuery job by its job ID. Use this to poll for completion of an async query job. | Name | Type | Required | Description | | ---------- | ------ | -------- | ------------------------------------------------------------ | | `job_id` | string | Yes | The ID of the job to retrieve | | `location` | string | No | Geographic location where the job was created, e.g. US or EU | ## `bigqueryserviceaccount_get_model` [Section titled “bigqueryserviceaccount\_get\_model”](#bigqueryserviceaccount_get_model) Retrieve metadata for a specific BigQuery ML model, including model type, feature columns, label columns, and training run details. | Name | Type | Required | Description | | ------------ | ------ | -------- | ------------------------------------------ | | `dataset_id` | string | Yes | The ID of the dataset containing the model | | `model_id` | string | Yes | The ID of the model to retrieve | ## `bigqueryserviceaccount_get_query_results` [Section titled “bigqueryserviceaccount\_get\_query\_results”](#bigqueryserviceaccount_get_query_results) Retrieve the results of a completed BigQuery query job. Supports pagination via page tokens. Use after polling Get Job until status is DONE. | Name | Type | Required | Description | | ------------- | ------- | -------- | ------------------------------------------------------------------------ | | `job_id` | string | Yes | The ID of the completed query job | | `location` | string | No | Geographic location where the job was created, e.g. US or EU | | `max_results` | integer | No | Maximum number of rows to return per page | | `page_token` | string | No | Page token from a previous response to retrieve the next page of results | | `timeout_ms` | integer | No | Maximum milliseconds to wait if the query has not yet completed | ## `bigqueryserviceaccount_get_routine` [Section titled “bigqueryserviceaccount\_get\_routine”](#bigqueryserviceaccount_get_routine) Retrieve the definition and metadata of a specific BigQuery routine (stored procedure or UDF), including its arguments, return type, and body. | Name | Type | Required | Description | | ------------ | ------ | -------- | -------------------------------------------- | | `dataset_id` | string | Yes | The ID of the dataset containing the routine | | `routine_id` | string | Yes | The ID of the routine to retrieve | ## `bigqueryserviceaccount_get_table` [Section titled “bigqueryserviceaccount\_get\_table”](#bigqueryserviceaccount_get_table) Retrieve metadata and schema for a specific BigQuery table or view, including column names, types, descriptions, and table properties. | Name | Type | Required | Description | | ------------ | ------ | -------- | ------------------------------------------ | | `dataset_id` | string | Yes | The ID of the dataset containing the table | | `table_id` | string | Yes | The ID of the table or view to retrieve | ## `bigqueryserviceaccount_list_datasets` [Section titled “bigqueryserviceaccount\_list\_datasets”](#bigqueryserviceaccount_list_datasets) List all BigQuery datasets in the project. Supports filtering by label and pagination. | Name | Type | Required | Description | | ------------- | ------- | -------- | ----------------------------------------------------------------- | | `all` | boolean | No | If true, includes hidden datasets in the results | | `filter` | string | No | Label filter expression to restrict results, e.g. labels.env:prod | | `max_results` | integer | No | Maximum number of datasets to return per page | | `page_token` | string | No | Page token from a previous response to retrieve the next page | ## `bigqueryserviceaccount_list_jobs` [Section titled “bigqueryserviceaccount\_list\_jobs”](#bigqueryserviceaccount_list_jobs) List BigQuery jobs in the project. Supports filtering by state and projection, and pagination. | Name | Type | Required | Description | | -------------- | ------- | -------- | -------------------------------------------------------------------------------------------------- | | `all_users` | boolean | No | If true, returns jobs for all users in the project; otherwise returns only the current user’s jobs | | `max_results` | integer | No | Maximum number of jobs to return per page | | `page_token` | string | No | Page token from a previous response to retrieve the next page | | `projection` | string | No | Controls the fields returned: minimal (default) or full | | `state_filter` | string | No | Filter jobs by state: done, pending, or running | ## `bigqueryserviceaccount_list_models` [Section titled “bigqueryserviceaccount\_list\_models”](#bigqueryserviceaccount_list_models) List all BigQuery ML models in a dataset, including their model type, training status, and creation time. | Name | Type | Required | Description | | ------------- | ------- | -------- | ------------------------------------------------------------- | | `dataset_id` | string | Yes | The ID of the dataset to list models from | | `max_results` | integer | No | Maximum number of models to return per page | | `page_token` | string | No | Page token from a previous response to retrieve the next page | ## `bigqueryserviceaccount_list_routines` [Section titled “bigqueryserviceaccount\_list\_routines”](#bigqueryserviceaccount_list_routines) List all stored procedures and user-defined functions (UDFs) in a BigQuery dataset. | Name | Type | Required | Description | | ------------- | ------- | -------- | ------------------------------------------------------------------------ | | `dataset_id` | string | Yes | The ID of the dataset to list routines from | | `filter` | string | No | Filter expression to restrict results, e.g. routineType:SCALAR\_FUNCTION | | `max_results` | integer | No | Maximum number of routines to return per page | | `page_token` | string | No | Page token from a previous response to retrieve the next page | ## `bigqueryserviceaccount_list_table_data` [Section titled “bigqueryserviceaccount\_list\_table\_data”](#bigqueryserviceaccount_list_table_data) Read rows directly from a BigQuery table without writing a SQL query. Supports pagination, row offset, and field selection. | Name | Type | Required | Description | | ----------------- | ------- | -------- | ---------------------------------------------------------------------------- | | `dataset_id` | string | Yes | The ID of the dataset containing the table | | `max_results` | integer | No | Maximum number of rows to return per page | | `page_token` | string | No | Page token from a previous response to retrieve the next page | | `selected_fields` | string | No | Comma-separated list of fields to return; if omitted all fields are returned | | `start_index` | integer | No | Zero-based row index to start reading from | | `table_id` | string | Yes | The ID of the table to read rows from | ## `bigqueryserviceaccount_list_tables` [Section titled “bigqueryserviceaccount\_list\_tables”](#bigqueryserviceaccount_list_tables) List all tables and views in a BigQuery dataset. Supports pagination. | Name | Type | Required | Description | | ------------- | ------- | -------- | ------------------------------------------------------------- | | `dataset_id` | string | Yes | The ID of the dataset to list tables from | | `max_results` | integer | No | Maximum number of tables to return per page | | `page_token` | string | No | Page token from a previous response to retrieve the next page | ## `bigqueryserviceaccount_run_query` [Section titled “bigqueryserviceaccount\_run\_query”](#bigqueryserviceaccount_run_query) Execute a SQL query synchronously against BigQuery and return results immediately. Best for short-running queries. | Name | Type | Required | Description | | ---------------- | ------- | -------- | ------------------------------------------------------------------------------------ | | `create_session` | boolean | No | If true, creates a new session and returns a session ID in the response | | `dry_run` | boolean | No | If true, validates the query and returns estimated bytes processed without executing | | `location` | string | No | Geographic location of the dataset, e.g. US or EU | | `max_results` | integer | No | Maximum number of rows to return in the response | | `query` | string | Yes | SQL query to execute | | `timeout_ms` | integer | No | Maximum milliseconds to wait for query completion before returning | | `use_legacy_sql` | boolean | No | Use BigQuery legacy SQL syntax instead of standard SQL |
---
# DOCUMENT BOUNDARY
---
# Box
> Connect to Box to manage files, folders, users, tasks, webhooks, collaborations, and more using OAuth 2.0.
Connect to Box to manage files, folders, users, groups, collaborations, tasks, comments, webhooks, search, and more using the Box REST API.  Supports authentication: OAuth 2.0  ## Set up the agent connector [Section titled “Set up the agent connector”](#set-up-the-agent-connector) Connect Box to Scalekit so your agent can manage files, folders, users, tasks, and more on behalf of your users. Box uses OAuth 2.0 — users authorize access through Box’s login flow, and Scalekit handles token storage and refresh automatically. You will need: * A Box developer account (free at [developer.box.com](https://developer.box.com)) * Your Box OAuth app’s Client ID and Client Secret * The redirect URI from Scalekit to paste into Box 1. ### Create a Box OAuth app * Go to the [Box Developer Console](https://app.box.com/developers/console) and click **Create New App**. * Select **Custom App** as the app type. * Under authentication method, choose **User Authentication (OAuth 2.0)**. This lets your agent act on behalf of each user who authorizes access. * Enter an app name (e.g. “My Agent App”) and click **Create App**.  2. ### Copy the redirect URI from Scalekit * In [Scalekit dashboard](https://app.scalekit.com), go to **AgentKit** > **Connections** > **Create Connection**. * Find **Box** and click **Create**. * Click **Use your own credentials** and copy the redirect URI. It looks like: `https://.scalekit.cloud/sso/v1/oauth//callback`  3. ### Add the redirect URI to Box * In the [Box Developer Console](https://app.box.com/developers/console), open your app and go to the **Configuration** tab. * Under **OAuth 2.0 Redirect URI**, paste the redirect URI from Scalekit and click **Save Changes**.  4. ### Select scopes for your app Still on the **Configuration** tab in Box, scroll down to **Application Scopes** and enable the permissions your agent needs: | Scope | Required for | | ------------------------------ | ---------------------------------------------- | | `root_readonly` | Reading files and folders | | `root_readwrite` | Creating, updating, and deleting files/folders | | `manage_groups` | Creating and managing groups | | `manage_webhook` | Creating and managing webhooks | | `manage_managed_users` | Creating and managing enterprise users | | `manage_enterprise_properties` | Accessing enterprise events | Click **Save Changes** after selecting scopes. 5. ### Add credentials in Scalekit * In the [Box Developer Console](https://app.box.com/developers/console), open your app → **Configuration** tab. * Copy your **Client ID** and **Client Secret**. * In [Scalekit dashboard](https://app.scalekit.com), go to **AgentKit** > **Connections**, open the Box connection you created, and enter: * **Client ID** — from Box * **Client Secret** — from Box * **Scopes** — select the same scopes you enabled in Box (e.g. `root_readonly`, `root_readwrite`)  * Click **Save**. 6. ### Add a connected account for each user Each user who authorizes Box access becomes a connected account. During authorization, Box will show your app name and request the scopes you configured. **Via dashboard (for testing)** * In [Scalekit dashboard](https://app.scalekit.com), go to your Box connection → **Connected Accounts** → **Add Account**. * Enter a **User ID** (your internal identifier for this user, e.g. `user_123`). * Click **Add** — you will be redirected to Box’s OAuth consent screen to authorize.  **Via API (for production)** In production, generate an authorization link and redirect your user to it: * Node.js
```typescript
1
const { link } = await scalekit.actions.getAuthorizationLink({
2
connectionName: 'box',
3
identifier: 'user_123',
4
});
5
// Redirect your user to `link`
```
* Python
```python
1
link_response = scalekit_client.actions.get_authorization_link(
2
connection_name="box",
3
identifier="user_123",
4
)
5
# Redirect your user to link_response.link
```
After the user authorizes, Scalekit stores their tokens. Your agent can then call Box tools on their behalf without any further redirects. ## Usage [Section titled “Usage”](#usage) ## Getting resource IDs [Section titled “Getting resource IDs”](#getting-resource-ids) Most Box tools require an ID for the resource they operate on. Here is where to find each ID: | Resource | Tool to get ID | Response field | | ------------------- | ------------------------------------------------------------------ | -------------------------------------------------------- | | File ID | `box_folder_items_list` (folder\_id: `"0"`) | `entries[].id` where `entries[].type == "file"` | | Folder ID | `box_folder_items_list` (folder\_id: `"0"`) | `entries[].id` where `entries[].type == "folder"` | | Task ID | `box_file_tasks_list` or `box_task_create` response | `id` | | Task assignment ID | `box_task_assignments_list` | `entries[].id` | | Comment ID | `box_file_comments_list` | `entries[].id` | | Collaboration ID | `box_folder_collaborations_list` or `box_file_collaborations_list` | `entries[].id` | | Collection ID | `box_collections_list` | `entries[].id` (Favorites collection = type `favorites`) | | Webhook ID | `box_webhooks_list` | `entries[].id` | | User ID | `box_user_me_get` (authenticated user) or `box_users_list` | `id` | | Group ID | `box_groups_list` | `entries[].id` | | Group membership ID | `box_group_members_list` or `box_user_memberships_list` | `entries[].id` | | Web link ID | `box_folder_items_list` | `entries[].id` where `entries[].type == "web_link"` | Collaboration ID vs User ID The `collaboration_id` is different from the collaborating user’s ID. After creating a collaboration with `box_collaboration_create`, fetch the collaboration ID using `box_folder_collaborations_list` or `box_file_collaborations_list`. ## Required scopes [Section titled “Required scopes”](#required-scopes) Enable the corresponding Box app scopes before calling tools that need them: | Tools | Required scope | | ------------------------------------------------------------------------- | ------------------------------ | | All file/folder read tools, `box_file_representations_get` | `root_readonly` | | File/folder create, update, delete | `root_readwrite` | | `box_group_*`, `box_user_memberships_list` | `manage_groups` | | `box_webhook_*`, `box_webhooks_list` | `manage_webhook` | | `box_user_create`, `box_user_delete`, `box_users_list`, `box_user_update` | `manage_managed_users` | | `box_events_list` (enterprise stream) | `manage_enterprise_properties` | ## Tool list [Section titled “Tool list”](#tool-list) ### Files [Section titled “Files”](#files) ## `box_file_get` [Section titled “box\_file\_get”](#box_file_get) Retrieves detailed information about a file. | Name | Type | Required | Description | | --------- | ------ | -------- | ------------------------------------------------------------------------ | | `file_id` | string | Yes | ID of the file. Get it from `box_folder_items_list` on folder\_id `"0"`. | | `fields` | string | No | Comma-separated list of fields to return. | ## `box_file_update` [Section titled “box\_file\_update”](#box_file_update) Updates a file’s name, description, tags, or moves it to another folder. | Name | Type | Required | Description | | ------------- | ------ | -------- | --------------------------------------- | | `file_id` | string | Yes | ID of the file to update. | | `name` | string | No | New name for the file. | | `description` | string | No | New description for the file. | | `parent_id` | string | No | ID of the folder to move the file into. | | `tags` | string | No | Comma-separated list of tags. | ## `box_file_delete` [Section titled “box\_file\_delete”](#box_file_delete) Moves a file to the trash. | Name | Type | Required | Description | | --------- | ------ | -------- | ------------------------- | | `file_id` | string | Yes | ID of the file to delete. | ## `box_file_copy` [Section titled “box\_file\_copy”](#box_file_copy) Creates a copy of a file in a specified folder. | Name | Type | Required | Description | | ----------- | ------ | -------- | ---------------------------------------- | | `file_id` | string | Yes | ID of the file to copy. | | `parent_id` | string | Yes | ID of the destination folder. | | `name` | string | No | New name for the copied file (optional). | ## `box_file_versions_list` [Section titled “box\_file\_versions\_list”](#box_file_versions_list) Retrieves all previous versions of a file. | Name | Type | Required | Description | | --------- | ------ | -------- | --------------- | | `file_id` | string | Yes | ID of the file. | ## `box_file_thumbnail_get` [Section titled “box\_file\_thumbnail\_get”](#box_file_thumbnail_get) Retrieves a thumbnail image for a file. | Name | Type | Required | Description | | ------------ | ------- | -------- | ------------------------------------------ | | `file_id` | string | Yes | ID of the file. | | `extension` | string | Yes | Thumbnail format: `jpg` or `png`. | | `min_width` | integer | No | Minimum width of the thumbnail in pixels. | | `min_height` | integer | No | Minimum height of the thumbnail in pixels. | ## `box_file_representations_get` [Section titled “box\_file\_representations\_get”](#box_file_representations_get) Retrieves available representations for a file, such as PDFs, extracted text, or image thumbnails. Box generates representations on demand — poll until the `status` is `success` before downloading. | Name | Type | Required | Description | | ------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------- | | `file_id` | string | Yes | ID of the file. Get it from `box_folder_items_list`. | | `x_rep_hints` | string | Yes | Representation formats to request, e.g. `[pdf][extracted_text]` or `[jpg?dimensions=320x320]`. Multiple formats can be combined. | ### Folders [Section titled “Folders”](#folders) ## `box_folder_get` [Section titled “box\_folder\_get”](#box_folder_get) Retrieves a folder’s details and its immediate items. | Name | Type | Required | Description | | ----------- | ------- | -------- | ------------------------------------------------ | | `folder_id` | string | Yes | ID of the folder. Use `"0"` for the root folder. | | `fields` | string | No | Comma-separated list of fields to return. | | `sort` | string | No | Sort order: `id`, `name`, `date`, or `size`. | | `direction` | string | No | Sort direction: `ASC` or `DESC`. | | `offset` | integer | No | Pagination offset. | | `limit` | integer | No | Max items to return (max 1000). | ## `box_folder_items_list` [Section titled “box\_folder\_items\_list”](#box_folder_items_list) Retrieves a paginated list of items in a folder. Use folder\_id `"0"` to start from the root. | Name | Type | Required | Description | | ----------- | ------- | -------- | ------------------------------------------------ | | `folder_id` | string | Yes | ID of the folder. Use `"0"` for the root folder. | | `fields` | string | No | Comma-separated list of fields to return. | | `sort` | string | No | Sort field: `id`, `name`, `date`, or `size`. | | `direction` | string | No | `ASC` or `DESC`. | | `offset` | integer | No | Pagination offset. | | `limit` | integer | No | Max items to return (max 1000). | ## `box_folder_create` [Section titled “box\_folder\_create”](#box_folder_create) Creates a new folder inside a parent folder. | Name | Type | Required | Description | | ----------- | ------ | -------- | -------------------------------------------- | | `name` | string | Yes | Name of the new folder. | | `parent_id` | string | Yes | ID of the parent folder. Use `"0"` for root. | | `fields` | string | No | Comma-separated list of fields to return. | ## `box_folder_update` [Section titled “box\_folder\_update”](#box_folder_update) Updates a folder’s name, description, or moves it. | Name | Type | Required | Description | | ------------- | ------ | -------- | ----------------------------------------- | | `folder_id` | string | Yes | ID of the folder to update. | | `name` | string | No | New name for the folder. | | `description` | string | No | New description for the folder. | | `parent_id` | string | No | ID of the new parent folder to move into. | ## `box_folder_delete` [Section titled “box\_folder\_delete”](#box_folder_delete) Moves a folder to the trash. Deleting non-empty folders Pass `recursive: "true"` when deleting a folder that contains files or subfolders. Box rejects the request if the folder has contents and `recursive` is omitted. | Name | Type | Required | Description | | ----------- | ------ | -------- | -------------------------------------------------------------------- | | `folder_id` | string | Yes | ID of the folder to delete. | | `recursive` | string | No | Must be `"true"` to delete folders that contain files or subfolders. | ## `box_folder_copy` [Section titled “box\_folder\_copy”](#box_folder_copy) Creates a copy of a folder and its contents. | Name | Type | Required | Description | | ----------- | ------ | -------- | ------------------------------------------ | | `folder_id` | string | Yes | ID of the folder to copy. | | `parent_id` | string | Yes | ID of the destination folder. | | `name` | string | No | New name for the copied folder (optional). | ### Search [Section titled “Search”](#search) ## `box_search` [Section titled “box\_search”](#box_search) Searches files, folders, and web links in Box. | Name | Type | Required | Description | | --------------------- | ------- | -------- | ---------------------------------------------------------------------------------------- | | `query` | string | Yes | Search query string. | | `type` | string | No | Filter by type: `file`, `folder`, or `web_link`. | | `ancestor_folder_ids` | string | No | Comma-separated folder IDs to scope the search. | | `content_types` | string | No | Comma-separated content types: `name`, `description`, `tag`, `comments`, `file_content`. | | `file_extensions` | string | No | Comma-separated file extensions to filter (e.g. `pdf,docx`). | | `created_at_range` | string | No | ISO 8601 date range: `2024-01-01T00:00:00Z,2024-12-31T23:59:59Z`. | | `updated_at_range` | string | No | Date range for last updated. | | `owner_user_ids` | string | No | Comma-separated user IDs to filter by owner. | | `scope` | string | No | Search scope: `user_content` or `enterprise_content`. | | `limit` | integer | No | Max results (max 200). | | `offset` | integer | No | Pagination offset. | | `fields` | string | No | Comma-separated list of fields to return. | ## `box_recent_items_list` [Section titled “box\_recent\_items\_list”](#box_recent_items_list) Retrieves files and folders the user accessed recently. | Name | Type | Required | Description | | -------- | ------- | -------- | ------------------------------------------- | | `fields` | string | No | Comma-separated list of fields to return. | | `limit` | integer | No | Max results. | | `marker` | string | No | Pagination marker from a previous response. | ### Collaborations [Section titled “Collaborations”](#collaborations) ## `box_collaboration_create` [Section titled “box\_collaboration\_create”](#box_collaboration_create) Grants a user or group access to a file or folder. | Name | Type | Required | Description | | -------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------ | | `item_id` | string | Yes | ID of the file or folder. | | `item_type` | string | Yes | Type of item: `file` or `folder`. | | `accessible_by_id` | string | Yes | Box user or group ID to grant access to. Get user IDs from `box_users_list`. | | `accessible_by_type` | string | Yes | Type: `user` or `group`. | | `role` | string | Yes | Collaboration role: `viewer`, `previewer`, `uploader`, `previewer_uploader`, `viewer_uploader`, `co-owner`, or `editor`. | | `notify` | string | No | Notify collaborator via email (`true`/`false`). | | `can_view_path` | string | No | Allow user to see path to item (`true`/`false`). | | `expires_at` | string | No | Expiry date in ISO 8601 format. | ## `box_collaboration_get` [Section titled “box\_collaboration\_get”](#box_collaboration_get) Retrieves details of a specific collaboration. | Name | Type | Required | Description | | ------------------ | ------ | -------- | ------------------------------------------------------------------------------------------------------ | | `collaboration_id` | string | Yes | ID of the collaboration. Get it from `box_folder_collaborations_list` — this is **not** the user’s ID. | | `fields` | string | No | Comma-separated list of fields to return. | ## `box_collaboration_update` [Section titled “box\_collaboration\_update”](#box_collaboration_update) Updates the role or status of a collaboration. | Name | Type | Required | Description | | ------------------ | ------- | -------- | ---------------------------------------------------------------------- | | `collaboration_id` | string | Yes | ID of the collaboration. Get it from `box_folder_collaborations_list`. | | `role` | string | No | New collaboration role. | | `status` | string | No | Collaboration status: `accepted` or `rejected`. | | `expires_at` | string | No | New expiry date in ISO 8601 format. | | `can_view_path` | boolean | No | Allow user to see path to item. | ## `box_collaboration_delete` [Section titled “box\_collaboration\_delete”](#box_collaboration_delete) Removes a collaboration, revoking user or group access. | Name | Type | Required | Description | | ------------------ | ------ | -------- | -------------------------------------------------------------------------------- | | `collaboration_id` | string | Yes | ID of the collaboration to delete. Get it from `box_folder_collaborations_list`. | ## `box_file_collaborations_list` [Section titled “box\_file\_collaborations\_list”](#box_file_collaborations_list) Retrieves all collaborations on a file. | Name | Type | Required | Description | | --------- | ------ | -------- | ----------------------------------------- | | `file_id` | string | Yes | ID of the file. | | `fields` | string | No | Comma-separated list of fields to return. | ## `box_folder_collaborations_list` [Section titled “box\_folder\_collaborations\_list”](#box_folder_collaborations_list) Retrieves all collaborations on a folder. | Name | Type | Required | Description | | ----------- | ------ | -------- | ----------------------------------------- | | `folder_id` | string | Yes | ID of the folder. | | `fields` | string | No | Comma-separated list of fields to return. | ### Comments [Section titled “Comments”](#comments) ## `box_comment_create` [Section titled “box\_comment\_create”](#box_comment_create) Adds a comment to a file. | Name | Type | Required | Description | | ---------------- | ------ | -------- | -------------------------------------------------- | | `item_id` | string | Yes | ID of the file to comment on. | | `item_type` | string | Yes | Type of item: `file` or `comment` (for replies). | | `message` | string | Yes | Text of the comment. | | `tagged_message` | string | No | Comment text with `@[user_id:user_name]` mentions. | ## `box_comment_get` [Section titled “box\_comment\_get”](#box_comment_get) Retrieves a comment. | Name | Type | Required | Description | | ------------ | ------ | -------- | -------------------------------------------------------- | | `comment_id` | string | Yes | ID of the comment. Get it from `box_file_comments_list`. | | `fields` | string | No | Comma-separated list of fields to return. | ## `box_comment_update` [Section titled “box\_comment\_update”](#box_comment_update) Updates the text of a comment. | Name | Type | Required | Description | | ------------ | ------ | -------- | ---------------------------- | | `comment_id` | string | Yes | ID of the comment to update. | | `message` | string | Yes | New text for the comment. | ## `box_comment_delete` [Section titled “box\_comment\_delete”](#box_comment_delete) Removes a comment. | Name | Type | Required | Description | | ------------ | ------ | -------- | ---------------------------- | | `comment_id` | string | Yes | ID of the comment to delete. | ## `box_file_comments_list` [Section titled “box\_file\_comments\_list”](#box_file_comments_list) Retrieves all comments on a file. | Name | Type | Required | Description | | --------- | ------ | -------- | ----------------------------------------- | | `file_id` | string | Yes | ID of the file. | | `fields` | string | No | Comma-separated list of fields to return. | ### Tasks [Section titled “Tasks”](#tasks) ## `box_task_create` [Section titled “box\_task\_create”](#box_task_create) Creates a task on a file. | Name | Type | Required | Description | | ----------------- | ------ | -------- | -------------------------------------------------------------------------- | | `file_id` | string | Yes | ID of the file to attach the task to. Get it from `box_folder_items_list`. | | `message` | string | No | Task message/description. | | `action` | string | No | Action: `review` or `complete`. | | `due_at` | string | No | Due date in ISO 8601 format (e.g. `2025-12-31T00:00:00Z`). | | `completion_rule` | string | No | Completion rule: `all_assignees` or `any_assignee`. | ## `box_task_get` [Section titled “box\_task\_get”](#box_task_get) Retrieves a task’s details. | Name | Type | Required | Description | | --------- | ------ | -------- | -------------------------------------------------- | | `task_id` | string | Yes | ID of the task. Get it from `box_file_tasks_list`. | ## `box_task_update` [Section titled “box\_task\_update”](#box_task_update) Updates a task’s message, due date, or completion rule. | Name | Type | Required | Description | | ----------------- | ------ | -------- | ------------------------------------------------------- | | `task_id` | string | Yes | ID of the task to update. | | `message` | string | No | New message for the task. | | `due_at` | string | No | New due date in ISO 8601 format. | | `action` | string | No | New action: `review` or `complete`. | | `completion_rule` | string | No | New completion rule: `all_assignees` or `any_assignee`. | ## `box_task_delete` [Section titled “box\_task\_delete”](#box_task_delete) Removes a task from a file. | Name | Type | Required | Description | | --------- | ------ | -------- | ------------------------- | | `task_id` | string | Yes | ID of the task to delete. | ## `box_file_tasks_list` [Section titled “box\_file\_tasks\_list”](#box_file_tasks_list) Retrieves all tasks associated with a file. | Name | Type | Required | Description | | --------- | ------ | -------- | --------------- | | `file_id` | string | Yes | ID of the file. | ## `box_task_assignment_create` [Section titled “box\_task\_assignment\_create”](#box_task_assignment_create) Assigns a task to a user. | Name | Type | Required | Description | | ------------ | ------ | -------- | ------------------------------------------------------------------- | | `task_id` | string | Yes | ID of the task to assign. Get it from `box_file_tasks_list`. | | `user_id` | string | No | ID of the user to assign the task to. Get it from `box_users_list`. | | `user_login` | string | No | Email login of the user (alternative to `user_id`). | ## `box_task_assignment_get` [Section titled “box\_task\_assignment\_get”](#box_task_assignment_get) Retrieves a specific task assignment. | Name | Type | Required | Description | | -------------------- | ------ | -------- | ------------------------------------------------------------------- | | `task_assignment_id` | string | Yes | ID of the task assignment. Get it from `box_task_assignments_list`. | ## `box_task_assignment_update` [Section titled “box\_task\_assignment\_update”](#box_task_assignment_update) Updates a task assignment (complete, approve, or reject). | Name | Type | Required | Description | | -------------------- | ------ | -------- | ----------------------------------------------------------------------- | | `task_assignment_id` | string | Yes | ID of the task assignment. | | `message` | string | No | Optional message/comment for the resolution. | | `resolution_state` | string | No | Resolution state: `completed`, `incomplete`, `approved`, or `rejected`. | Completed tasks Box returns a `403` error when you try to delete an assignment on a completed task. This is expected API behavior — only delete assignments on tasks with `incomplete` status. ## `box_task_assignment_delete` [Section titled “box\_task\_assignment\_delete”](#box_task_assignment_delete) Removes a task assignment from a user. | Name | Type | Required | Description | | -------------------- | ------ | -------- | ------------------------------------ | | `task_assignment_id` | string | Yes | ID of the task assignment to remove. | ## `box_task_assignments_list` [Section titled “box\_task\_assignments\_list”](#box_task_assignments_list) Retrieves all assignments for a task. | Name | Type | Required | Description | | --------- | ------ | -------- | --------------- | | `task_id` | string | Yes | ID of the task. | ### Shared links [Section titled “Shared links”](#shared-links) ## `box_shared_link_file_create` [Section titled “box\_shared\_link\_file\_create”](#box_shared_link_file_create) Creates or updates a shared link for a file. | Name | Type | Required | Description | | -------------- | ------- | -------- | ---------------------------------------------------------------- | | `file_id` | string | Yes | ID of the file. | | `access` | string | No | Shared link access level: `open`, `company`, or `collaborators`. | | `unshared_at` | string | No | Expiry date in ISO 8601 format. | | `password` | string | No | Password to protect the shared link. | | `can_download` | boolean | No | Allow download (`true`/`false`). | | `can_preview` | boolean | No | Allow preview (`true`/`false`). | ## `box_shared_link_folder_create` [Section titled “box\_shared\_link\_folder\_create”](#box_shared_link_folder_create) Creates or updates a shared link for a folder. | Name | Type | Required | Description | | -------------- | ------- | -------- | ---------------------------------------------------------------- | | `folder_id` | string | Yes | ID of the folder. | | `access` | string | No | Shared link access level: `open`, `company`, or `collaborators`. | | `unshared_at` | string | No | Expiry date in ISO 8601 format. | | `password` | string | No | Password to protect the shared link. | | `can_download` | boolean | No | Allow download (`true`/`false`). | ### Collections [Section titled “Collections”](#collections) ## `box_collections_list` [Section titled “box\_collections\_list”](#box_collections_list) Retrieves all collections for the user (e.g. Favorites). | Name | Type | Required | Description | | -------- | ------- | -------- | ----------------------------------------- | | `fields` | string | No | Comma-separated list of fields to return. | | `offset` | integer | No | Pagination offset. | | `limit` | integer | No | Max results. | ## `box_collection_items_list` [Section titled “box\_collection\_items\_list”](#box_collection_items_list) Retrieves the items in a collection. Use `box_collections_list` first to get the collection ID. | Name | Type | Required | Description | | --------------- | ------- | -------- | --------------------------------------------------------- | | `collection_id` | string | Yes | ID of the collection. Get it from `box_collections_list`. | | `fields` | string | No | Comma-separated list of fields to return. | | `offset` | integer | No | Pagination offset. | | `limit` | integer | No | Max results. | ### Metadata [Section titled “Metadata”](#metadata) ## `box_file_metadata_create` [Section titled “box\_file\_metadata\_create”](#box_file_metadata_create) Applies metadata to a file using a metadata template. Requires an enterprise metadata template. | Name | Type | Required | Description | | -------------- | ------ | -------- | ---------------------------------------------------------------------------------- | | `file_id` | string | Yes | ID of the file. | | `scope` | string | Yes | Template scope: `global` or `enterprise`. | | `template_key` | string | Yes | Key of the metadata template. Get it from `box_metadata_templates_list`. | | `data_json` | string | Yes | JSON string of metadata fields and values, e.g. `"{\"department\": \"Finance\"}"`. | ## `box_file_metadata_get` [Section titled “box\_file\_metadata\_get”](#box_file_metadata_get) Retrieves a specific metadata instance on a file. | Name | Type | Required | Description | | -------------- | ------ | -------- | ----------------------------------------- | | `file_id` | string | Yes | ID of the file. | | `scope` | string | Yes | Template scope: `global` or `enterprise`. | | `template_key` | string | Yes | Key of the metadata template. | ## `box_file_metadata_list` [Section titled “box\_file\_metadata\_list”](#box_file_metadata_list) Retrieves all metadata instances attached to a file. | Name | Type | Required | Description | | --------- | ------ | -------- | --------------- | | `file_id` | string | Yes | ID of the file. | ## `box_file_metadata_delete` [Section titled “box\_file\_metadata\_delete”](#box_file_metadata_delete) Removes a metadata instance from a file. | Name | Type | Required | Description | | -------------- | ------ | -------- | ----------------------------------------- | | `file_id` | string | Yes | ID of the file. | | `scope` | string | Yes | Template scope: `global` or `enterprise`. | | `template_key` | string | Yes | Key of the metadata template. | ## `box_folder_metadata_list` [Section titled “box\_folder\_metadata\_list”](#box_folder_metadata_list) Retrieves all metadata instances on a folder. | Name | Type | Required | Description | | ----------- | ------ | -------- | ----------------- | | `folder_id` | string | Yes | ID of the folder. | ## `box_metadata_template_get` [Section titled “box\_metadata\_template\_get”](#box_metadata_template_get) Retrieves a metadata template schema. Returns `404` if no enterprise templates exist. | Name | Type | Required | Description | | -------------- | ------ | -------- | ------------------------------------------------ | | `scope` | string | Yes | Scope of the template: `global` or `enterprise`. | | `template_key` | string | Yes | Key of the metadata template. | ## `box_metadata_templates_list` [Section titled “box\_metadata\_templates\_list”](#box_metadata_templates_list) Retrieves all metadata templates for the enterprise. | Name | Type | Required | Description | | -------- | ------- | -------- | ------------------ | | `marker` | string | No | Pagination marker. | | `limit` | integer | No | Max results. | ### Web links [Section titled “Web links”](#web-links) ## `box_web_link_create` [Section titled “box\_web\_link\_create”](#box_web_link_create) Creates a web link (bookmark) inside a folder. | Name | Type | Required | Description | | ------------- | ------ | -------- | -------------------------------------------- | | `url` | string | Yes | URL of the web link. | | `parent_id` | string | Yes | ID of the parent folder. Use `"0"` for root. | | `name` | string | No | Name for the web link. | | `description` | string | No | Description of the web link. | ## `box_web_link_get` [Section titled “box\_web\_link\_get”](#box_web_link_get) Retrieves a web link’s details. | Name | Type | Required | Description | | ------------- | ------ | -------- | --------------------------------------------------------------------------- | | `web_link_id` | string | Yes | ID of the web link. Get it from `box_folder_items_list` (type: `web_link`). | | `fields` | string | No | Comma-separated list of fields to return. | ## `box_web_link_update` [Section titled “box\_web\_link\_update”](#box_web_link_update) Updates a web link’s URL, name, or description. | Name | Type | Required | Description | | ------------- | ------ | -------- | ----------------------------- | | `web_link_id` | string | Yes | ID of the web link to update. | | `url` | string | No | New URL. | | `name` | string | No | New name. | | `description` | string | No | New description. | | `parent_id` | string | No | New parent folder ID. | ## `box_web_link_delete` [Section titled “box\_web\_link\_delete”](#box_web_link_delete) Removes a web link. | Name | Type | Required | Description | | ------------- | ------ | -------- | ----------------------------- | | `web_link_id` | string | Yes | ID of the web link to delete. | ### Trash [Section titled “Trash”](#trash) ## `box_trash_list` [Section titled “box\_trash\_list”](#box_trash_list) Retrieves items in the user’s trash. | Name | Type | Required | Description | | ----------- | ------- | -------- | ----------------------------------------- | | `fields` | string | No | Comma-separated list of fields to return. | | `limit` | integer | No | Max results. | | `offset` | integer | No | Pagination offset. | | `sort` | string | No | Sort field: `name`, `date`, or `size`. | | `direction` | string | No | Sort direction: `ASC` or `DESC`. | ## `box_trash_file_restore` [Section titled “box\_trash\_file\_restore”](#box_trash_file_restore) Restores a file from the trash. | Name | Type | Required | Description | | ----------- | ------ | -------- | --------------------------------------------------------- | | `file_id` | string | Yes | ID of the trashed file. | | `name` | string | No | New name if the original name is already taken. | | `parent_id` | string | No | Parent folder ID if the original location is unavailable. | ## `box_trash_file_permanently_delete` [Section titled “box\_trash\_file\_permanently\_delete”](#box_trash_file_permanently_delete) Permanently deletes a trashed file. This action cannot be undone. | Name | Type | Required | Description | | --------- | ------ | -------- | ----------------------- | | `file_id` | string | Yes | ID of the trashed file. | ## `box_trash_folder_restore` [Section titled “box\_trash\_folder\_restore”](#box_trash_folder_restore) Restores a folder from the trash. | Name | Type | Required | Description | | ----------- | ------ | -------- | ---------------------------------------------------- | | `folder_id` | string | Yes | ID of the trashed folder. | | `name` | string | No | New name if the original is already taken. | | `parent_id` | string | No | New parent folder ID if the original is unavailable. | ## `box_trash_folder_permanently_delete` [Section titled “box\_trash\_folder\_permanently\_delete”](#box_trash_folder_permanently_delete) Permanently deletes a trashed folder. This action cannot be undone. | Name | Type | Required | Description | | ----------- | ------ | -------- | ------------------------- | | `folder_id` | string | Yes | ID of the trashed folder. | ### Webhooks [Section titled “Webhooks”](#webhooks) Webhooks require the `manage_webhook` scope. ## `box_webhook_create` [Section titled “box\_webhook\_create”](#box_webhook_create) Creates a webhook to receive event notifications when something changes in a file or folder. | Name | Type | Required | Description | | ------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `target_id` | string | Yes | ID of the file or folder to watch. | | `target_type` | string | Yes | Type of target: `file` or `folder`. | | `address` | string | Yes | HTTPS URL to receive webhook notifications. Must be publicly accessible. | | `triggers` | array | Yes | Array of event strings, e.g. `["FILE.UPLOADED","FILE.DELETED"]`. See [Box webhook triggers](https://developer.box.com/reference/resources/webhook/) for the full list. | ## `box_webhook_get` [Section titled “box\_webhook\_get”](#box_webhook_get) Retrieves a webhook’s details. | Name | Type | Required | Description | | ------------ | ------ | -------- | --------------------------------------------------- | | `webhook_id` | string | Yes | ID of the webhook. Get it from `box_webhooks_list`. | ## `box_webhook_update` [Section titled “box\_webhook\_update”](#box_webhook_update) Updates a webhook’s address or triggers. | Name | Type | Required | Description | | ------------- | ------ | -------- | ------------------------------------ | | `webhook_id` | string | Yes | ID of the webhook to update. | | `address` | string | No | New HTTPS URL for notifications. | | `triggers` | array | No | New array of event strings. | | `target_id` | string | No | New target ID. | | `target_type` | string | No | New target type: `file` or `folder`. | ## `box_webhook_delete` [Section titled “box\_webhook\_delete”](#box_webhook_delete) Removes a webhook. | Name | Type | Required | Description | | ------------ | ------ | -------- | ---------------------------- | | `webhook_id` | string | Yes | ID of the webhook to delete. | ## `box_webhooks_list` [Section titled “box\_webhooks\_list”](#box_webhooks_list) Retrieves all webhooks for the application. | Name | Type | Required | Description | | -------- | ------- | -------- | ------------------ | | `marker` | string | No | Pagination marker. | | `limit` | integer | No | Max results. | ### Users [Section titled “Users”](#users) User management tools require the `manage_managed_users` scope. Users created with Box must use an email address within the enterprise’s verified domain. ## `box_user_me_get` [Section titled “box\_user\_me\_get”](#box_user_me_get) Retrieves information about the currently authenticated user. No parameters required — use this to get your own user ID. | Name | Type | Required | Description | | -------- | ------ | -------- | ----------------------------------------- | | `fields` | string | No | Comma-separated list of fields to return. | ## `box_user_get` [Section titled “box\_user\_get”](#box_user_get) Retrieves information about a specific user. | Name | Type | Required | Description | | --------- | ------ | -------- | ------------------------------------------------------------------ | | `user_id` | string | Yes | ID of the user. Get it from `box_users_list` or `box_user_me_get`. | | `fields` | string | No | Comma-separated list of fields to return. | ## `box_users_list` [Section titled “box\_users\_list”](#box_users_list) Retrieves all users in the enterprise. | Name | Type | Required | Description | | ------------- | ------- | -------- | ------------------------------------------------ | | `filter_term` | string | No | Filter users by name or login. | | `user_type` | string | No | Filter by type: `all`, `managed`, or `external`. | | `fields` | string | No | Comma-separated list of fields to return. | | `limit` | integer | No | Max users to return. | | `offset` | integer | No | Pagination offset. | ## `box_user_create` [Section titled “box\_user\_create”](#box_user_create) Creates a new managed user in the enterprise. | Name | Type | Required | Description | | ------------------------- | ------- | -------- | ------------------------------------------------------------------------------ | | `name` | string | Yes | Full name of the user. | | `login` | string | No | Email address (login) for managed users. Must be within the enterprise domain. | | `role` | string | No | User role: `user` or `coadmin`. | | `space_amount` | integer | No | Storage quota in bytes (`-1` for unlimited). | | `is_platform_access_only` | boolean | No | Set `true` for app users (no login required). | ## `box_user_update` [Section titled “box\_user\_update”](#box_user_update) Updates a user’s properties in the enterprise. | Name | Type | Required | Description | | ---------------- | ------- | -------- | ---------------------------------------------------------- | | `user_id` | string | Yes | ID of the user to update. | | `name` | string | No | New full name. | | `role` | string | No | New role: `user` or `coadmin`. | | `status` | string | No | New status: `active`, `inactive`, or `cannot_delete_edit`. | | `space_amount` | integer | No | Storage quota in bytes. | | `tracking_codes` | string | No | Tracking codes as a JSON array string. | ## `box_user_delete` [Section titled “box\_user\_delete”](#box_user_delete) Removes a user from the enterprise. | Name | Type | Required | Description | | --------- | ------ | -------- | ---------------------------------------------------------- | | `user_id` | string | Yes | ID of the user to delete. | | `notify` | string | No | Notify user via email (`true`/`false`). | | `force` | string | No | Force deletion even if user owns content (`true`/`false`). | ## `box_user_memberships_list` [Section titled “box\_user\_memberships\_list”](#box_user_memberships_list) Retrieves all group memberships for a user. | Name | Type | Required | Description | | --------- | ------- | -------- | ------------------ | | `user_id` | string | Yes | ID of the user. | | `limit` | integer | No | Max results. | | `offset` | integer | No | Pagination offset. | ### Groups [Section titled “Groups”](#groups) Group tools require the `manage_groups` scope. ## `box_groups_list` [Section titled “box\_groups\_list”](#box_groups_list) Retrieves all groups in the enterprise. | Name | Type | Required | Description | | ------------- | ------- | -------- | ----------------------------------------- | | `filter_term` | string | No | Filter groups by name. | | `fields` | string | No | Comma-separated list of fields to return. | | `limit` | integer | No | Max results. | | `offset` | integer | No | Pagination offset. | ## `box_group_create` [Section titled “box\_group\_create”](#box_group_create) Creates a new group in the enterprise. | Name | Type | Required | Description | | -------------------------- | ------ | -------- | ---------------------------------------------------------------------------------------- | | `name` | string | Yes | Name of the group. | | `description` | string | No | Description of the group. | | `provenance` | string | No | Identifier to distinguish manually created vs synced groups. | | `invitability_level` | string | No | Who can invite to group: `admins_only`, `admins_and_members`, or `all_managed_users`. | | `member_viewability_level` | string | No | Who can view group members: `admins_only`, `admins_and_members`, or `all_managed_users`. | ## `box_group_get` [Section titled “box\_group\_get”](#box_group_get) Retrieves information about a group. | Name | Type | Required | Description | | ---------- | ------ | -------- | ----------------------------------------------- | | `group_id` | string | Yes | ID of the group. Get it from `box_groups_list`. | | `fields` | string | No | Comma-separated list of fields to return. | ## `box_group_update` [Section titled “box\_group\_update”](#box_group_update) Updates a group’s properties. | Name | Type | Required | Description | | -------------------------- | ------ | -------- | ---------------------------------------------------------------------------- | | `group_id` | string | Yes | ID of the group to update. | | `name` | string | No | New name for the group. | | `description` | string | No | New description. | | `invitability_level` | string | No | Who can invite: `admins_only`, `admins_and_members`, or `all_managed_users`. | | `member_viewability_level` | string | No | Who can view members. | ## `box_group_delete` [Section titled “box\_group\_delete”](#box_group_delete) Permanently deletes a group. | Name | Type | Required | Description | | ---------- | ------ | -------- | -------------------------- | | `group_id` | string | Yes | ID of the group to delete. | ## `box_group_members_list` [Section titled “box\_group\_members\_list”](#box_group_members_list) Retrieves all members of a group. | Name | Type | Required | Description | | ---------- | ------- | -------- | ------------------ | | `group_id` | string | Yes | ID of the group. | | `limit` | integer | No | Max results. | | `offset` | integer | No | Pagination offset. | ## `box_group_membership_add` [Section titled “box\_group\_membership\_add”](#box_group_membership_add) Adds a user to a group. | Name | Type | Required | Description | | ---------- | ------ | -------- | ---------------------------------------------------- | | `user_id` | string | Yes | ID of the user to add. Get it from `box_users_list`. | | `group_id` | string | Yes | ID of the group. | | `role` | string | No | Role in the group: `member` or `admin`. | ## `box_group_membership_get` [Section titled “box\_group\_membership\_get”](#box_group_membership_get) Retrieves a specific group membership. | Name | Type | Required | Description | | --------------------- | ------ | -------- | ----------------------------------------------------------------- | | `group_membership_id` | string | Yes | ID of the group membership. Get it from `box_group_members_list`. | | `fields` | string | No | Comma-separated list of fields to return. | ## `box_group_membership_update` [Section titled “box\_group\_membership\_update”](#box_group_membership_update) Updates a user’s role in a group. | Name | Type | Required | Description | | --------------------- | ------ | -------- | ------------------------------- | | `group_membership_id` | string | Yes | ID of the membership to update. | | `role` | string | No | New role: `member` or `admin`. | ## `box_group_membership_remove` [Section titled “box\_group\_membership\_remove”](#box_group_membership_remove) Removes a user from a group. | Name | Type | Required | Description | | --------------------- | ------ | -------- | --------------------------------------------------------------------------- | | `group_membership_id` | string | Yes | ID of the group membership to remove. Get it from `box_group_members_list`. | ### Events [Section titled “Events”](#events) ## `box_events_list` [Section titled “box\_events\_list”](#box_events_list) Retrieves events from the Box event stream. Use `admin_logs` for enterprise-wide events (requires `manage_enterprise_properties` scope). | Name | Type | Required | Description | | ----------------- | ------- | -------- | ------------------------------------------------------------- | | `stream_type` | string | No | Event stream type: `all`, `changes`, `sync`, or `admin_logs`. | | `stream_position` | string | No | Pagination position from a previous response. | | `limit` | integer | No | Max events to return. | | `event_type` | string | No | Comma-separated list of event types to filter. | | `created_after` | string | No | Return events after this date (ISO 8601). | | `created_before` | string | No | Return events before this date (ISO 8601). |
---
# DOCUMENT BOUNDARY
---
# Glossary
> A comprehensive glossary of terms related to authentication, authorization, and identity management in B2B SaaS applications.
## Access Token [Section titled “Access Token”](#access-token) * **Definition**: A credential (often a JWT) issued by the authorization server that the client uses to access the resource server. It represents the client’s authorization and typically has an expiry time and scopes attached. The resource server validates this token. ## Administrator [Section titled “Administrator”](#administrator) * **Definition**: An IT administrator responsible for managing identity provider configurations within a customer organization. ## Admin Portal [Section titled “Admin Portal”](#admin-portal) * **Definition**: A customizable web interface for customers’ IT administrators to manage identity provider configurations. ## AI Agent Identity and Attestation [Section titled “AI Agent Identity and Attestation”](#ai-agent-identity-and-attestation) * **Definition**: A process by which an AI agent proves its identity to an authorization server, often using cryptographic evidence (e.g. signed JWT assertions or hardware-backed keys), so the server can trust requests coming from that agent. ## API Endpoint [Section titled “API Endpoint”](#api-endpoint) * **Definition**: A specific URL where an API can be accessed to perform specific operations or retrieve data. ## API Key [Section titled “API Key”](#api-key) * **Definition**: A unique identifier used to authenticate API requests to Scalekit, allowing secure access to the platform’s features and services. ## App [Section titled “App”](#app) * **Definition**: Another term for an application, representing the software product or service sold to customers. ## Application [Section titled “Application”](#application) * **Definition**: The software product or service offered by B2B App developers to customers. * **Example**: A workspace can contain multiple applications. ## Audit Log [Section titled “Audit Log”](#audit-log) * **Definition**: A record of all activities and changes made within the B2B App, used for security and compliance purposes. ## Authentication [Section titled “Authentication”](#authentication) * **Definition**: The process of verifying the identity of a user or system attempting to access the B2B App. ## Authorization [Section titled “Authorization”](#authorization) * **Definition**: The process of determining what actions or resources a user is allowed to access within the B2B App. ## Authorization Server [Section titled “Authorization Server”](#authorization-server) * **Definition**: The server in OAuth that authenticates clients and issues tokens (could be a part of your SaaS or a third-party IdP like Okta Azure AD, etc.). It essentially says “Yes, client X, here is a token proving you are authenticated and allowed to do Y.” ## Authorization URL [Section titled “Authorization URL”](#authorization-url) * **Definition**: The URL to which users are redirected to grant authorization for the B2B App. ## B2B App [Section titled “B2B App”](#b2b-app) * **Definition**: An application designed for use by other businesses or organizations to streamline operations. ## B2B SaaS App [Section titled “B2B SaaS App”](#b2b-saas-app) * **Definition**: A type of B2B App delivered over the internet, allowing access without local installation. ## Claims [Section titled “Claims”](#claims) * **Definition**: Information about a user that is passed from an identity provider to a service provider during authentication. ## Client Credentials Flow [Section titled “Client Credentials Flow”](#client-credentials-flow) * **Definition**: The OAuth process where a machine client exchanges its client ID and secret for an access token from the auth server. No user involved. The resulting token represents the machine and carries scopes for what it can do. ## Configuration [Section titled “Configuration”](#configuration) * **Definition**: The settings and parameters that define how the B2B App interacts with Scalekit and other services. ## Connection [Section titled “Connection”](#connection) * **Definition**: A link between the B2B App and a customer’s identity provider for enabling Single Sign-On (SSO). * **Example**: Each organization can have its own unique connection. ## Customer [Section titled “Customer”](#customer) * **Definition**: A business or organization that uses the application to meet specific needs. ## Custom Attribute [Section titled “Custom Attribute”](#custom-attribute) * **Definition**: Additional fields added to user data in Scalekit for storing extra information. ## Dashboard [Section titled “Dashboard”](#dashboard) * **Definition**: The main control panel within Scalekit for configuring settings, viewing analytics, and managing integrations. ## Deprovisioning [Section titled “Deprovisioning”](#deprovisioning) * **Definition**: The process of removing user access and accounts when they are no longer needed or authorized. ## Directory Provider [Section titled “Directory Provider”](#directory-provider) * **Definition**: An organization offering directory services, including identity providers. ## Directory Sync [Section titled “Directory Sync”](#directory-sync) * **Definition**: A module in Scalekit for automatic provisioning and deprovisioning of user accounts. ## Documentation [Section titled “Documentation”](#documentation) * **Definition**: Comprehensive guides and references that explain how to use and integrate with Scalekit’s features and services. ## Dynamic Client Registration [Section titled “Dynamic Client Registration”](#dynamic-client-registration) * **Definition**: A protocol (RFC 7591) that allows a client application to programmatically register itself with an authorization server to obtain credentials (client ID/secret, etc.). Useful for large-scale or third-party ecosystems where manual registration of clients is not feasible or to enable self-service integration in a controlled way. ## Environment [Section titled “Environment”](#environment) * **Definition**: Different versions or instances of an application, such as test and live environments. * **Example**: Each environment has its own settings and is isolated for security. ## Error Handling [Section titled “Error Handling”](#error-handling) * **Definition**: The process of managing and responding to errors that occur during API calls or application operations. ## Federation [Section titled “Federation”](#federation) * **Definition**: The process of establishing trust between different identity providers and service providers for seamless authentication. ## ID Token [Section titled “ID Token”](#id-token) * **Definition**: A JSON Web Token (JWT) issued by the identity provider containing user identity information. ## Identity Provider (IdP) [Section titled “Identity Provider (IdP)”](#identity-provider-idp) * **Definition**: A service that verifies user identity and provides information about user attributes. ## IdP Simulator [Section titled “IdP Simulator”](#idp-simulator) * **Definition**: A tool that mimics the behavior of an identity provider for testing integrations. ## Integration [Section titled “Integration”](#integration) * **Definition**: The process of connecting Scalekit with other systems or services to enable seamless data flow and functionality. ## JWT [Section titled “JWT”](#jwt) * **Definition**: A standard format for representing claims securely between two parties. It is a compact, URL-safe means of representing claims securely between two parties. ## Logout [Section titled “Logout”](#logout) * **Definition**: The process of ending a user’s session and revoking their access to the B2B App. ## Machine-to-Machine (M2M) Authentication [Section titled “Machine-to-Machine (M2M) Authentication”](#machine-to-machine-m2m-authentication) * **Definition**: Methods for verifying identity between two automated services or software entities without human intervention. Ensures a client program (machine) is trusted by the service it calls, typically via tokens, keys, or certificates. ## MFA (Multi-Factor Authentication) [Section titled “MFA (Multi-Factor Authentication)”](#mfa-multi-factor-authentication) * **Definition**: A security feature that requires users to provide multiple forms of verification before accessing the B2B App. ## Model Context Protocol (MCP) [Section titled “Model Context Protocol (MCP)”](#model-context-protocol-mcp) * **Definition**: A new protocol (spearheaded by Anthropic and others) to standardize how AI models (assistants) can interact with external tools and data. It defines how AI agents can discover available “tools” (APIs) and the context to call them. For auth, MCP leverages OAuth 2.1 – effectively requiring AI agents to go through a secure authorization process to get access to those tools. Think of it as an evolving standard to make AI to SaaS integrations plug-and-play, with security built-in via OAuth. ## Mutual TLS (mTLS) [Section titled “Mutual TLS (mTLS)”](#mutual-tls-mtls) * **Definition**: A transport layer security mechanism where *both client and server present certificates* to mutually authenticate each other during the TLS handshake. Provides strong assurance of identities at connection level and encrypts the traffic. Used in high-security environments and internal service-to-service auth. ## Normalized Payload [Section titled “Normalized Payload”](#normalized-payload) * **Definition**: A standardized format for data sent from Scalekit to the B2B App. ## OAuth [Section titled “OAuth”](#oauth) * **Definition**: A standard protocol for authorization enabling limited access to user data. ## OAuth 2.0/OAuth 2.1 [Section titled “OAuth 2.0/OAuth 2.1”](#oauth-20oauth-21) * **Definition**: An authorization framework widely used for granting access to resources. OAuth 2.0 defines various *flows* (grant types) for different scenarios (authorization code, client credentials, etc.). OAuth 2.1 is an incremental update that compiles security best practices (PKCE required, no legacy flows, etc.). In M2M context, OAuth’s **Client Credentials Grant** is most relevant, allowing a service to get an access token using its own credentials. ## OAuth 2.0 Token Exchange (RFC 8693) [Section titled “OAuth 2.0 Token Exchange (RFC 8693)”](#oauth-20-token-exchange-rfc-8693) * **Definition**: A protocol that lets one token be exchanged for another—for example, an AI agent exchanging its machine-client token for a token scoped to call a downstream service on behalf of a user or another service. Enables delegation and impersonation scenarios. ## OIDC [Section titled “OIDC”](#oidc) * **Definition**: A standard protocol for authentication that builds on OAuth 2.0. ## OpenID Connect (OIDC) [Section titled “OpenID Connect (OIDC)”](#openid-connect-oidc) * **Definition**: An identity layer on top of OAuth 2.0 (often used for user authentication). Mentioned here because the discovery document and id\_token concepts come from OIDC. OIDC isn’t directly about M2M auth (it’s user-centric), but the OIDC discovery (`.well-known`) and JWT usage are leveraged in service auth too. ## Organization [Section titled “Organization”](#organization) * **Definition**: The customers of B2B Apps, typically businesses. * **Example**: Each business is considered an organization with its own users. ## PKCE (Proof Key for Code Exchange) [Section titled “PKCE (Proof Key for Code Exchange)”](#pkce-proof-key-for-code-exchange) * **Definition**: An extension to OAuth used to prevent interception of authorization codes. The client generates a random secret (code verifier) and sends a hashed version (code challenge) in the auth request, then must present the original secret when redeeming the code. Ensures that even if an attacker intercepts the auth code, they can’t exchange it without the secret. PKCE is now recommended for any OAuth client that can’t secure a client secret – including mobile, SPA, and some machine clients. ## PKI (Public Key Infrastructure) [Section titled “PKI (Public Key Infrastructure)”](#pki-public-key-infrastructure) * **Definition**: The system of certificate authorities, processes, and tools for managing digital certificates (like those used in mTLS). Involves issuing certs, distributing them, rotating when expired, revoking if compromised, etc. A robust PKI is needed to effectively use certificate-based auth at scale. ## Provisioning [Section titled “Provisioning”](#provisioning) * **Definition**: The process of creating and managing user accounts and access rights in the B2B App. ## Rate Limiting [Section titled “Rate Limiting”](#rate-limiting) * **Definition**: A mechanism that controls the rate of requests a user or application can make to the API within a specific time period. ## Refresh Token [Section titled “Refresh Token”](#refresh-token) * **Definition**: A long-lived token that can be used to get new access tokens without re-authenticating. In M2M auth, refresh tokens are rarely used because the client can just use its credentials again. Refresh tokens are more for user-based flows to avoid prompting the user frequently. ## Resource Server [Section titled “Resource Server”](#resource-server) * **Definition**: The API or service that the client wants to use – it receives tokens from clients and decides whether to accept them (by validating them). In our context, your SaaS API is a resource server that expects a valid token for requests. ## Role-Based Access Control (RBAC) [Section titled “Role-Based Access Control (RBAC)”](#role-based-access-control-rbac) * **Definition**: A method of regulating access to resources based on the roles of individual users within an organization. ## SAML Assertion [Section titled “SAML Assertion”](#saml-assertion) * **Definition**: A statement by an identity provider indicating a user’s authentication status. ## SCIM [Section titled “SCIM”](#scim) * **Definition**: SCIM (System for Cross-domain Identity Management) is a standard protocol for automating the provisioning and deprovisioning of user accounts and their attributes between an identity provider and a service provider. ## Scopes [Section titled “Scopes”](#scopes) * **Definition**: Strings that define what access is being requested or granted in an OAuth token. For example, `read:inventory` or `payments:create`. Scopes let the token carry permissions, enabling the resource server to allow or deny requests based on scope. Principle of least privilege is implemented by granting minimal scopes. ## Service Account [Section titled “Service Account”](#service-account) * **Definition**: A non-human account used by a software service. In context, it’s an identity set up for a machine to use. For example, a service account could be created for “Data Sync Service” in a customer’s tenant on your app. Service accounts have credentials (like client ID/secret or keys) to authenticate, and usually have roles or scopes assigned just like a user would. They enable organization-level or service-level tokens without tying to an actual person. ## Service Provider [Section titled “Service Provider”](#service-provider) * **Definition**: An entity offering a product or service to another organization or individual, especially in SSO contexts. ## Session [Section titled “Session”](#session) * **Definition**: A period of interaction between a user and the B2B App, typically starting with authentication and ending with logout. ## Social Connection [Section titled “Social Connection”](#social-connection) * **Definition**: Allows users to sign in using their social media accounts. ## SSO (Single Sign-On) [Section titled “SSO (Single Sign-On)”](#sso-single-sign-on) * **Definition**: An authentication method that allows users to access multiple applications with a single set of credentials. ## Team Member [Section titled “Team Member”](#team-member) * **Definition**: Individuals from the B2B App developer’s company who use Scalekit to manage applications. * **Roles**: Can include developers, product managers, or customer support staff. ## Tenant [Section titled “Tenant”](#tenant) * **Definition**: An isolated instance of the B2B App for a specific customer organization, with its own data and configurations. ## Token [Section titled “Token”](#token) * **Definition**: A piece of data that represents a user’s authentication status and permissions, used for accessing protected resources. ## User [Section titled “User”](#user) * **Definition**: An individual who uses the B2B App, typically belonging to a customer organization. ## User Attribute [Section titled “User Attribute”](#user-attribute) * **Definition**: Properties describing a user’s identity, used for authentication and access control. ## Webhook [Section titled “Webhook”](#webhook) * **Definition**: A mechanism for the B2B App to receive notifications or updates from Scalekit. ## Webhook Payload [Section titled “Webhook Payload”](#webhook-payload) * **Definition**: The data sent by Scalekit to the B2B App when a webhook is triggered, containing information about the event. ## Workspace [Section titled “Workspace”](#workspace) * **Definition**: A centralized hub for B2B App developers to manage applications and settings. * **Example**: Think of it as a command center for efficient application management. ## Zero Trust Security [Section titled “Zero Trust Security”](#zero-trust-security) * **Definition**: A security model where no user or device is inherently trusted, even if inside the network. Every access request must be authenticated, authorized, and continuously validated. For M2M, this means authenticating every service communication, minimizing implicit trust, and verifying identities at multiple layers (network & application). It often involves micro-segmentation and strict identity and access management for every machine identity.
---
# DOCUMENT BOUNDARY
---
# Interceptor triggers
> The points in the authentication flow where Scalekit calls your interceptor endpoint
## `PRE_SIGNUP` [Section titled “PRE\_SIGNUP”](#pre_signup) Fires before a user creates a new organization. Use this to validate email domains, check against blocklists, or enforce custom signup policies. ### Request body from Scalekit [Section titled “Request body from Scalekit”](#request-body-from-scalekit) PRE\_SIGNUP — request body
```json
1
{
2
"display_name": "Validate email domain",
3
"trigger_point": "PRE_SIGNUP",
4
"interceptor_context": {
5
"environment_id": "env_92561807201272162",
6
"user_id": "usr_93418238346728951", // Present only if user exists in another organization
7
"user_email": "john.doe@acmecorp.com", // Email attempting to sign up
8
"connection_details": [
9
{
10
"id": "conn_92561808744978132",
11
"type": "OAUTH", // OAUTH, SAML, OIDC, or PASSWORDLESS
12
"provider": "GOOGLE" // Identity provider used for authentication
13
}
14
],
15
//Contains parameters from the /oauth/authorize request
16
"auth_request": {
17
"connection_id": "conn_81665025441299343",
18
"organization_id": "org_102953846317318346",
19
"domain": "foocorp.com",
20
"login_hint": "john.doe@example.com",
21
"state": "xsrPHl7k7ARgdhC6"
22
},
23
"device_type": "Desktop", // Desktop, Mobile, Tablet, or Unknown
24
"ip_address": "203.0.113.24", // Client's IP address for geolocation or blocklist checks
25
"region": "IN", // Two-letter country code
26
"city": "Bengaluru",
27
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...",
28
"triggered_at": "2025-10-09T09:48:02.875Z" // ISO 8601 timestamp
29
},
30
"data": {
31
// User object present only when user already exists in another organization
32
"user": {
33
"id": "usr_93418238346728951",
34
"name": "John Doe",
35
"email": "john.doe@acmecorp.com",
36
"email_verified": true,
37
"created_at": "2025-10-06T11:06:49.120Z",
38
"updated_at": "2025-10-06T13:33:06.479Z",
39
"given_name": "John",
40
"family_name": "Doe",
41
"metadata": {
42
"type": "social_user"
43
},
44
"memberships": [ // Existing organization memberships
45
{
46
"organization_id": "org_93418204671239864",
47
"status": "ACTIVE",
48
"roles": [
49
"admin"
50
],
51
"metadata": {
52
"cost": {
53
"category": "platform",
54
"region": "US"
55
},
56
"department": "engineering"
57
},
58
"organization_name": "Example inc"
59
}
60
]
61
}
62
}
63
}
```
### Response format to return [Section titled “Response format to return”](#response-format-to-return) PRE\_SIGNUP — response body
```json
1
{
2
// Required: choose ALLOW or DENY
3
"decision": "DENY", // ALLOW | DENY
4
// Optional with DENY
5
"error": {
6
"message": "Only @acmecorp.com email addresses are allowed to sign up" // Shown to user when DENY
7
},
8
// Optional with ALLOW, Include when the user is to be provisioned in an existing organization.
9
"response": {
10
"create_organization_membership": {
11
// either external_organization_id or organization_id is required
12
"external_organization_id": "ext_B6YycAGRaPmnuxAFPT5KI4HBHxr4qWX",
13
"organization_id": "org_102953846317318346",
14
"roles": [
15
"admin",
16
"viewer"
17
]
18
}
19
}
20
}
```
## `PRE_SESSION_CREATION` [Section titled “PRE\_SESSION\_CREATION”](#pre_session_creation) Fires before session tokens are issued for a user. Use this to add custom claims to the access token, apply conditional access policies, or integrate with external authorization systems. ### Request body from Scalekit [Section titled “Request body from Scalekit”](#request-body-from-scalekit-1) PRE\_SESSION\_CREATION — request body
```json
1
{
2
"display_name": "Add custom claims to tokens",
3
"trigger_point": "PRE_SESSION_CREATION",
4
"interceptor_context": {
5
"environment_id": "env_92561807204567213",
6
"user_id": "usr_93418238346728951",
7
"user_email": "john.doe@acmecorp.com",
8
"organization_id": "org_93418204671239864", // Organization user is logging into
9
"connection_details": [
10
{
11
"id": "conn_92561808744978132",
12
"type": "OAUTH", // Authentication method used
13
"provider": "GOOGLE"
14
}
15
],
16
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...",
17
"device_type": "Desktop", // Desktop, Mobile, Tablet, or Unknown
18
"ip_address": "203.0.113.24", // Use for conditional access based on location
19
"region": "US", // Two-letter country code
20
"city": "San Francisco",
21
"triggered_at": "2025-10-08T15:22:42.381Z" // ISO 8601 timestamp
22
},
23
"data": {
24
"user": {
25
"id": "usr_93418238346728951",
26
"name": "John Doe",
27
"email": "john.doe@acmecorp.com",
28
"email_verified": true,
29
"created_at": "2025-10-06T11:06:49.120Z",
30
"updated_at": "2025-10-06T13:33:06.479Z",
31
"first_name": "John",
32
"last_name": "Doe",
33
"memberships": [ // All organizations this user belongs to
34
{
35
"organization_id": "org_93418204671239864",
36
"status": "ACTIVE"
37
}
38
]
39
}
40
}
41
}
```
### Response format to return [Section titled “Response format to return”](#response-format-to-return-1) PRE\_SESSION\_CREATION — response body
```json
1
{
2
"decision": "ALLOW", // Required: ALLOW to issue tokens, DENY to block login
3
"response": {
4
"claims": { // Optional: Custom claims added to the access token (under `custom_claims`)
5
"subscription_tier": "enterprise",
6
"data_region": "us-west-2",
7
"feature_flags": ["analytics_dashboard", "api_access", "custom_branding"],
8
"account_manager": "jane.smith@acmecorp.com"
9
}
10
}
11
}
```
## `PRE_USER_INVITATION` [Section titled “PRE\_USER\_INVITATION”](#pre_user_invitation) Fires before an invitation is created or sent for a new organization member. Use this to validate invitee email addresses, enforce invitation policies, or check user limits. ### Request body from Scalekit [Section titled “Request body from Scalekit”](#request-body-from-scalekit-2) PRE\_USER\_INVITATION — request body
```json
1
{
2
"display_name": "Validate invitation policy",
3
"trigger_point": "PRE_USER_INVITATION",
4
"interceptor_context": {
5
"environment_id": "env_92561807201272162",
6
"user_id": "usr_93418238346728951", // Present only if invitee already exists in another org
7
"user_email": "sarah.johnson@contractor.com", // Email address being invited
8
"organization_id": "org_93731871904672153", // Organization sending the invitation
9
"city": "Bengaluru",
10
"device_type": "Desktop", // Device of the person sending the invitation
11
"ip_address": "182.156.5.2", // IP of the person sending the invitation
12
"region": "IN", // Two-letter country code
13
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...",
14
"triggered_at": "2025-10-09T12:50:41.803Z" // ISO 8601 timestamp
15
},
16
"data": {
17
"organization": { // Organization details for context
18
"id": "org_93731871904672153",
19
"name": "Acme Corp"
20
}
21
}
22
}
```
### Response format to return [Section titled “Response format to return”](#response-format-to-return-2) PRE\_USER\_INVITATION — response body
```json
1
{
2
"decision": "DENY", // Required: ALLOW to send invitation, DENY to block
3
"error": {
4
"message": "Cannot invite users from external domains. Please use @acmecorp.com email addresses." // Shown when DENY
5
}
6
}
```
## `PRE_M2M_TOKEN_CREATION` [Section titled “PRE\_M2M\_TOKEN\_CREATION”](#pre_m2m_token_creation) Fires before issuing a machine-to-machine access token. Use this to add custom claims, modify scopes dynamically, or apply conditional access rules for service-to-service authentication. ### Request body from Scalekit [Section titled “Request body from Scalekit”](#request-body-from-scalekit-3) PRE\_M2M\_TOKEN\_CREATION — request body
```json
1
{
2
"display_name": "Validate M2M client permissions",
3
"trigger_point": "PRE_M2M_TOKEN_CREATION",
4
"interceptor_context": {
5
"environment_id": "env_17002334043308132",
6
"client_id": "m2morg_93710427703245914", // M2M client requesting the token
7
"user_agent": "deployment-service/2.1.0", // Service making the request
8
"device_type": "Unknown",
9
"triggered_at": "2025-10-08T21:22:20.173Z" // ISO 8601 timestamp
10
},
11
"data": {
12
"m2m_token_claims": { // Claims that will be included in the token
13
"client_id": "m2morg_93710427703245914",
14
"claims": {
15
"custom_claims": { // Existing custom claims from client configuration
16
"service_name": "deployment-automation",
17
"deployment_environment": "production"
18
},
19
"oid": "org_89669394174574792", // Organization ID for this M2M client
20
"scope": "deploy:applications read:deployments write:logs", // Space-separated scopes
21
"scopes": [ // Array of individual scopes requested
22
"deploy:applications",
23
"read:deployments",
24
"write:logs"
25
]
26
}
27
}
28
}
29
}
```
### Response format to return [Section titled “Response format to return”](#response-format-to-return-3) PRE\_M2M\_TOKEN\_CREATION — response body
```json
1
{
2
"decision": "ALLOW", // Required: ALLOW to issue token, DENY to block
3
"response": {
4
"claims": { // Optional: Add or modify claims in the M2M token
5
"scope": "deploy:applications read:deployments", // Can modify scopes dynamically
6
"aud": "https://api.acmecorp.com", // Target audience for the token
7
"rate_limit": "1000", // Custom claim for rate limiting
8
"environment": "production" // Custom claim for environment context
9
}
10
}
11
}
```
---
# DOCUMENT BOUNDARY
---
# Outbound IP addresses
> Allowlist Scalekit's outbound IP addresses so providers and services accept the requests and tool calls that originate from Scalekit.
When Scalekit makes outbound requests on your behalf, such as tool calls to upstream providers, the traffic originates from a fixed set of NAT IP addresses. If a provider or one of your own services restricts inbound traffic by IP, add these addresses to its allowlist so the provider accepts the requests. ## IP addresses by region [Section titled “IP addresses by region”](#ip-addresses-by-region) | Region | Outbound IP address | | ------------------- | ------------------- | | United States (US) | `34.94.129.140` | | European Union (EU) | `35.198.115.68` | Use the address for the region your Scalekit environment runs in. If you run environments in both regions, allowlist both addresses. ## When to allowlist these addresses [Section titled “When to allowlist these addresses”](#when-to-allowlist-these-addresses) Allowlist Scalekit’s outbound IP addresses when: * An upstream provider restricts API access to known IP addresses, and you call that provider’s tools through Scalekit. * Your own backend validates the source IP of the requests it receives from Scalekit.
---
# DOCUMENT BOUNDARY
---
# API rate limits
> Understand Scalekit API rate limits, tell them apart from upstream provider limits, handle 429 responses, and request a higher limit.
Scalekit applies a rate limit to the API requests from each environment. When a workload exceeds that limit, the API responds with HTTP `429 Too Many Requests`. This page explains how to recognize a rate-limit response, tell a Scalekit limit apart from an upstream provider’s limit, handle the response, and request a higher limit. ## How rate limits work [Section titled “How rate limits work”](#how-rate-limits-work) Scalekit enforces a per-environment request rate, measured in requests per minute. Scalekit tunes the limit per account, so high-throughput workloads can need a higher limit than the default. Routing MCP tool calls through Scalekit on top of authentication traffic is one example of a workload that can need more headroom. When you exceed the limit, Scalekit returns HTTP `429 Too Many Requests`. Back off and retry with exponential backoff rather than retrying immediately. ## Tell Scalekit limits apart from provider limits [Section titled “Tell Scalekit limits apart from provider limits”](#tell-scalekit-limits-apart-from-provider-limits) When you call tools through Scalekit, a `429` can come from either Scalekit or the upstream provider that Scalekit calls on your behalf, such as a CRM or data API. The `error_code` field on the error identifies the source: | `error_code` | Source | What to do | | -------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------- | | `RATE_LIMITED` | Scalekit’s own rate limit | Reduce the overall request frequency and back off before retrying. | | `TOOL_ERROR` | The upstream provider rate-limited the tool call | Apply the provider’s recommended backoff. Check the tool call logs for the provider’s message. | Review the detailed error in your dashboard’s tool call logs to confirm which provider and which tool triggered the limit. ## Handle a 429 response [Section titled “Handle a 429 response”](#handle-a-429-response) Every Scalekit SDK raises a dedicated exception when the API returns `429`. Catch it, read the error code to determine the source, and back off before retrying. * Node.js rate-limit-handling.ts
```ts
1
import { ScalekitTooManyRequestsException } from '@scalekit-sdk/node';
2
3
try {
4
// Your Scalekit SDK call, for example executing a tool
5
await scalekit.tools.executeTool(/* ... */);
6
} catch (error) {
7
if (error instanceof ScalekitTooManyRequestsException) {
8
// errorCode identifies the source of the 429 so you can back off correctly
9
if (error.errorCode === 'TOOL_ERROR') {
10
// Upstream provider rate-limited the call: apply provider-specific backoff
11
console.error('Provider rate limit:', error.message);
12
} else {
13
// Scalekit's own rate limit (RATE_LIMITED): reduce overall request frequency
14
console.error('Scalekit rate limit:', error.message);
15
}
16
}
17
}
```
* Python rate\_limit\_handling.py
```py
1
from scalekit.common.exceptions import ScalekitTooManyRequestsException
2
3
try:
4
result = scalekit_client.tools.execute_tool(...)
5
except ScalekitTooManyRequestsException as e:
6
# error_code identifies the source of the 429 so you can back off correctly
7
if e.error_code == "TOOL_ERROR":
8
# Upstream provider rate-limited the call: apply provider-specific backoff
9
print("Provider rate limit:", e.message)
10
else:
11
# Scalekit's own rate limit (RATE_LIMITED): reduce overall request frequency
12
print("Scalekit rate limit:", e.message)
```
* Go rate\_limit\_handling.go
```go
1
// Your Scalekit SDK call, for example executing a tool
2
_, err := scalekitClient.Tools.ExecuteTool(ctx /* ... */)
3
if err != nil {
4
// Inspect the error code to find the source of the 429.
5
// "TOOL_ERROR" is the upstream provider's limit; "RATE_LIMITED" is Scalekit's
6
// own limit. Back off with exponential backoff before retrying.
7
log.Printf("rate limited: %v", err)
8
}
```
* Java RateLimitHandling.java
```java
1
try {
2
// Your Scalekit SDK call, for example executing a tool
3
scalekitClient.tools().executeTool(/* ... */);
4
} catch (ScalekitException error) {
5
// Inspect the error code to find the source of the 429.
6
// "TOOL_ERROR" is the upstream provider's limit; "RATE_LIMITED" is Scalekit's
7
// own limit. Back off with exponential backoff before retrying.
8
System.err.println("Rate limited: " + error.getMessage());
9
}
```
## Request a higher limit [Section titled “Request a higher limit”](#request-a-higher-limit) If your workload needs a higher limit, contact Scalekit support with your account details and your expected peak requests per minute. Plan ahead before you route additional traffic, such as MCP tool calls, through Scalekit. Scalekit reviews the request and adjusts the limit for your account. When you estimate the limit you need, include headroom above your current peak so that normal spikes do not trigger `429` responses.