Skip to main content

User Management

Teams GET​

Gets all teams the current user is a member of.

Request Parameters​

import requests

key = '<api-key>'

url = f'https://api.sapling.ai/api/v1/team?key={key}'

try:
resp = requests.get(url)
if 200 <= resp.status_code < 300:
resp_json = resp.json()
print('Entries: ', resp_json)
else:
print('Error: ', str(resp.status_code), resp.text)
except Exception as e:
print('Error: ', e)

https://api.sapling.ai/api/v1/team?key=<key>

HTTP method: GET

key: String
32-character API key. Can also be supplied via the Authorization header as a bearer token; if both are provided, the key parameter takes precedence.

Response Parameters​

JSON array of team entries under key teams.

Team entry structure:

{
"id": <str, UUID>, // Opaque id, used for team management
"name": <str>, // Team name
}

Team POST​

Create a new team within an organization. This endpoint is available to enterprise plan API key holders who are owners or admins of the organization.

Request Parameters​

https://api.sapling.ai/api/v1/team

HTTP method: POST

Requires enterprise plan API key. User must be an owner or admin of the target organization.

key: String
32-character API key. Can also be supplied via the Authorization header as a bearer token; if both are provided, the key parameter takes precedence.

name: String
Name of the team to create. Leading and trailing whitespace is trimmed. The name must:

  • be non-empty and at most 64 characters
  • contain at most 2 digits
  • contain no control characters
  • contain no links (:// or www.)

It must also be unique among the organization's active teams. Deleted teams don't count.

organization_id: String (UUID)
UUID of the organization where the team will be created.

import requests

key = '<api-key>'
team_name = '<team-name>'
org_id = '<organization-id>'

url = 'https://api.sapling.ai/api/v1/team'
data = {
'key': key,
'name': team_name,
'organization_id': org_id,
}

try:
resp = requests.post(url, json=data)
if 200 <= resp.status_code < 300:
print('Success')
resp_json = resp.json()
print('Created team: ', resp_json)
else:
print('Error: ', str(resp.status_code), resp.text)
except Exception as e:
print('Error: ', e)

Response Parameters​

Success Response (201 Created)​

{
"id": "team-uuid",
"name": "Team Name",
"organization_id": "organization-uuid"
}

Error Responses​

402 Payment Required - No Enterprise Subscription

400 Bad Request - Missing or Invalid Parameters

The msg field says which check failed. For example:

  • Team name must be at most 64 characters.
  • Please avoid using numbers in team name.
  • Team name contains invalid characters.
  • Team name cannot contain a link.
  • Team name already exists.

403 Forbidden - Insufficient Permissions

401 Unauthorized - Invalid or Missing API Key

Example Usage​

cURL​

curl -X POST https://api.sapling.ai/api/v1/team \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Engineering Team",
"organization_id": "YOUR_ORGANIZATION_ID"
}'

Python​

import requests

url = "https://api.sapling.ai/api/v1/team"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
data = {
"name": "Engineering Team",
"organization_id": "YOUR_ORGANIZATION_ID"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())

JavaScript​

const response = await fetch('https://api.sapling.ai/api/v1/team', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Engineering Team',
organization_id: 'YOUR_ORGANIZATION_ID'
})
});

const data = await response.json();
console.log(data);

Behavior​

When a team is successfully created:

  1. The team inherits settings from the parent organization, such as data persistance.
  2. The team receives a subscription matching the organization's subscription:
    • Same tier (e.g., "enterprise")
    • Same end date (if applicable)
    • Same seat capacity (if applicable)
  3. The API key holder is automatically added to the team as an admin.

Notes​

  • The creating user must be a member of the organization with owner or admin privileges
  • Only users with enterprise subscriptions can use this endpoint
  • The endpoint returns the newly created team's UUID, which can be used with other team management endpoints

Team DELETE​

Delete a team within an organization. This endpoint is available to enterprise plan API key holders who are owners or admins of the organization. The team must belong to an organization.

Request Parameters​

https://api.sapling.ai/api/v1/team/<team_id>

HTTP method: DELETE

Requires enterprise plan API key. User must be an owner or admin of the organization that owns the team.

<team_id>: String (UUID)
UUID of the team to delete.

key: String
32-character API key. Can also be supplied via the Authorization header as a bearer token; if both are provided, the key parameter takes precedence.

import requests

key = '<api-key>'
team_id = '<TEAM_ID>'

url = f'https://api.sapling.ai/api/v1/team/{team_id}'
data = {
'key': key,
}

try:
resp = requests.delete(url, json=data)
if 200 <= resp.status_code < 300:
print('Success')
resp_json = resp.json()
print('Team deleted: ', resp_json)
else:
print('Error: ', str(resp.status_code), resp.text)
except Exception as e:
print('Error: ', e)

Response Parameters​

Success Response (200 OK)​

{
"msg": "Team deleted successfully."
}

Error Responses​

402 Payment Required - No Enterprise Subscription

400 Bad Request - Invalid Parameters

404 Not Found - Team Does Not Exist

403 Forbidden - Insufficient Permissions

401 Unauthorized - Invalid or Missing API Key

Example Usage​

cURL​

curl -X DELETE https://api.sapling.ai/api/v1/team/YOUR_ORGANIZATION_ID \
-H "Authorization: Bearer YOUR_API_KEY"

Python​

import requests

team_id = "YOUR_ORGANIZATION_ID"
url = f"https://api.sapling.ai/api/v1/team/{team_id}"
headers = {
"Authorization": "Bearer YOUR_API_KEY"
}

response = requests.delete(url, headers=headers)
print(response.json())

JavaScript​

const teamId = 'YOUR_ORGANIZATION_ID';
const response = await fetch(`https://api.sapling.ai/api/v1/team/${teamId}`, {
method: 'DELETE',
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
});

const data = await response.json();
console.log(data);

Behavior​

When a team is successfully deleted:

  1. All team members are deprovisioned from the team:
    • Team users are marked as deleted
    • User invites to the team are canceled
  2. Subscriptions for the team are ended:

Notes​

  • Only teams that belong to an organization can be deleted via this API endpoint
  • All team members will lose access to the team immediately
  • The deletion user must be an organization owner or admin, not just a team admin
  • Only users with enterprise subscriptions can use this endpoint
  • The operation cannot be undone via the API - contact support if you need to restore a deleted team

Team Users / Team Invites GET​

This endpoint is used to get the users and pending users for a team. Pending users are users who have an invite to the team but have not yet joined.

API key holder must be an admin for the team.

Request Parameters​

import requests

key = '<api-key>'
team_id = '<TEAM_ID>'

url = f'https://api.sapling.ai/api/v1/team/{team_id}/team_user?key={key}'

try:
resp = requests.get(url)
if 200 <= resp.status_code < 300:
print('Success')
else:
print('Error: ', str(resp.status_code), resp.text)
except Exception as e:
print('Error: ', e)

https://api.sapling.ai/api/v1/team/<team_id>/team_user?key=<key>

HTTP method: GET

API key holder must be an admin for the team.

<key>: String
32-character API key. Can also be supplied via the Authorization header as a bearer token; if both are provided, the key parameter takes precedence.

Response Parameters​

{
"users": <Team User>[], // Array of Team Users
"pending_users": <Pending User>[], // Array of Pending Users / Invites
}

Team User Structure:​

{
"id": <str, UUID>, // Opaque ID, used for management; each user has a unique id per team
"login_email": <str, email>,
"is_admin": <bool>,
"is_manager": <bool>,
"edit_permission": <bool>, // If user has edit permissions
"inspect_permission": <bool>, // If user has inspect permissions
"created_at": <str, date>, // e.g. "Wed, 07 Oct 2020 21:15:47 GMT"
"updated_at": <str, date>, // e.g. "Wed, 07 Oct 2020 21:15:47 GMT"
}

Pending User / Invite Structure:​

Pending Users have not joined the team yet. Once a user has registered an account and accepted the team invite, they will appear as a Team User.

{
"email": <str, email>, // Email that was invited
"team_id": <str, UUID>, // ID of team that user was invited to
"registered": <bool>, // If the email has registered for a Sapling account
"confirmed": <bool>, // If the Sapling account created has confirmed their email
"permissions": <str>, // Team permissions to be granted when user joins team
}

Team User POST​

API key holder must be an admin for the team.

If adding to teams without invites is allowed:

  • API key holder also must be a superuser.
  • An invite will still be sent if an account for the email has not been registered. Upon registration and email confirmation, the account will be automatically associated with the team.

Request Parameters​

import requests

key = '<api-key>'
team_id = '<TEAM_ID>'

url = f'https://api.sapling.ai/api/v1/team/{team_id}/team_user'
data = {
'key': key,
'email': '<user_email>',
}

try:
resp = requests.post(url, json=data)
if 200 <= resp.status_code < 300:
print('Success')
else:
print('Error: ', str(resp.status_code), resp.text)
except Exception as e:
print('Error: ', e)

https://api.sapling.ai/api/v1/team/<team_id>/team_user

HTTP method: POST

<team_id>: String (UUID)
ID of a Sapling team.

key: String
32-character API key. Can also be supplied via the Authorization header as a bearer token; if both are provided, the key parameter takes precedence.

email: String
Email of user to add to team; alternatively, set emails for multiple emails

emails: String
List of emails of users to add to team; all will have the same permissions. Alternatively, set email for a single email. NOTE For now, please use /team_user2 instead of /team_user in the API request URL to use the emails argument. This will be resolved in a future release.

is_admin: Optional Boolean
If the added user will be an admin for the team. Only available if adding to teams without invites is allowed. If the email provided does not have a user account (and an invite is sent), this argument is ignored.

is_manager: Optional Boolean
If the added user will be a manager for the team. Only available if adding to teams without invites is allowed. If the email provided does not have a user account (and an invite is sent), this argument is ignored.

edit_permission: Optional Boolean
If the added user will have edit permissions (dictionary, custom errors, snippets) for the team. Only available if adding to teams without invites is allowed. If the email provided does not have a user account (and an invite is sent), this argument is ignored.

inspect_permission: Optional Boolean
If the added user will have inspect permissions (can view reporting) for the team. Only available if adding to teams without invites is allowed. If the email provided does not have a user account (and an invite is sent), this argument is ignored.

Response Parameters​

Dictionary of the form:

{
"added": [...],
"invited": [...],
"errors": [...],
"already_exists": [...]
}

where added is a list of {'email': email, 'team_user': team_user_entry}, invited is a list of {'email': email}, errors is a list of {'email', email, 'reason': error_reason}, and already_exists is a list of {'email': email}.

Team User entry structure:

{
"id": <str, UUID>, // Opaque ID, used for management; each user has a unique id per team
"login_email": <str>,
"is_admin": <bool>
"is_manager": <bool>
"edit_permission": <bool>, // If user has edit permissions
"inspect_permission": <bool>, // If user has inspect permissions
"created_at": <str, date> // e.g. "Wed, 07 Oct 2020 21:15:47 GMT"
"updated_at": <str, date> // e.g. "Wed, 07 Oct 2020 21:15:47 GMT"
}

Invite limits​

The limit counts invite emails: people who don't have a confirmed Sapling account yet, or who can't be added directly. Each inviter can send at most 25 invite emails per day from a team that doesn't have an enterprise subscription.

Some invites are exempt:

  • invites from teams on an enterprise subscription
  • invites from inviters who hold their own active Pro, API or Enterprise subscription (a Pro Trial doesn't count, and neither does a subscription inherited through someone else's team or organization)

Some requests don't count toward the limit:

  • invites that were turned away
  • invites to someone who is already on the team
  • re-inviting the same address within 5 minutes, which returns the existing invite without sending another email

The window resets 24 hours after the first counted invite.

Once an inviter reaches the limit:

  • /team_user returns 400 with {"msg": "Daily invite limit reached for <email>. Contact support@sapling.ai to invite more people."}.
  • /team_user2 still returns 200. Each email over the limit is listed under errors with that message as its reason. Users added directly are unaffected.

Team User DELETE​

API key holder must be an admin for the team. This also deletes outstanding invites for the team-email pair, if any exist, but only if the user is already part of the team (otherwise, there is no team_user_id).

Request Parameters​

import requests

key = '<api-key>'
team_user_id = '<TEAM_USER_ID>'

url = f'https://api.sapling.ai/api/v1/team_user/{team_user_id}'
data = {
'key': key,
}

try:
resp = requests.delete(url, json=data)
if 200 <= resp.status_code < 300:
print('Success')
else:
print('Error: ', str(resp.status_code), resp.text)
except Exception as e:
print('Error: ', e)

https://api.sapling.ai/api/v1/team_user/<team_user_id>

HTTP method: DELETE

<team_user_id>: String (UUID)
ID of a Sapling team user.

key: String
32-character API key. Can also be supplied via the Authorization header as a bearer token; if both are provided, the key parameter takes precedence.

Response Parameters​

Empty, HTTP status code 204.

Team Users Bulk DELETE​

API key holder must be an admin for the team. This endpoint allows for bulk deletion of users from a team by providing a list of emails. It will attempt to delete each user specified and report which users were successfully deleted and which were not found. Users cannot delete themselves using this endpoint.

Request Parameters​

import requests

key = '<api-key>'
team_id = '<TEAM_ID>'
emails_to_delete = ['user1@example.com', 'user2@example.com']

url = f'https://api.sapling.ai/api/v1/team/{team_id}/team_users/bulk_delete'
data = {
'key': key,
'emails': emails_to_delete,
}

try:
resp = requests.delete(url, json=data)
if 200 <= resp.status_code < 300:
resp_json = resp.json()
print('Success:', resp_json)
else:
print('Error:', str(resp.status_code), resp.text)
except Exception as e:
print('Error:', e)

https://api.sapling.ai/api/v1/team/<team_id>/team_users/bulk_delete

HTTP method: DELETE

<team_id>: String (UUID)
ID of the Sapling team from which users will be deleted.

key: String
32-character API key. Can also be supplied via the Authorization header as a bearer token; if both are provided, the key parameter takes precedence. (must belong to a team admin).

emails: List of Strings
A list of email addresses for the users to be deleted from the team.

Response Parameters​

JSON dictionary containing the results of the bulk delete operation.

Success status code: 200

{
"deleted_users": [
{"id": "<UUID>", "email": "<user1@example.com>"},
// ... other deleted users
],
"not_found_users": [
"<user_not_in_team@example.com>"
// ... other users not found
],
"warning": "" // Reserved for future use
}

deleted_users: List
List of dictionaries, each containing the id (Team User ID) and email of a user successfully deleted from the team.

not_found_users: List
List of emails that were provided in the request but did not correspond to any user in the specified team.

Error status codes:

  • 400: Bad Request (e.g., missing/invalid emails list, invalid team_id, attempt to delete self).
  • 401/403: Unauthorized (API key holder is not an admin for the team).

Team User PATCH​

API key holder must be an admin for the team.

Request Parameters​

import requests

key = '<api-key>'
team_user_id = '<TEAM_USER_ID>'

url = f'https://api.sapling.ai/api/v1/team_user/{team_user_id}'
data = {
'key': key,
'is_admin': True,
}

try:
resp = requests.patch(url, json=data)
if 200 <= resp.status_code < 300:
print('Success')
else:
print('Error: ', str(resp.status_code), resp.text)
except Exception as e:
print('Error: ', e)

https://api.sapling.ai/api/v1/team_user/<team_user_id>

HTTP method: PATCH

<team_user_id>: String (UUID)
ID of a Sapling team user.

key: String
32-character API key. Can also be supplied via the Authorization header as a bearer token; if both are provided, the key parameter takes precedence.

is_admin: Optional Boolean
If the added user will be an admin for the team.

is_manager: Optional Boolean
If the added user will be a manager for the team.

edit_permission: Optional Boolean
If the added user will have edit permissions (dictionary, custom errors, snippets) for the team.

inspect_permission: Optional Boolean
If the added user will have inspect permissions (can view reporting) for the team.

Response Parameters​

Empty, HTTP status code 204.

Team User Invite DELETE​

API key holder must be an admin for the team. This deletes outstanding invites for the team-email pair, if any exist, even if the user has not joined the team.

Request Parameters​

import requests

key = '<api-key>'
email = '<EMAIL>'

url = f'https://api.sapling.ai/api/v1/team_user_invite/{team_id}'
data = {
'key': key,
'email': email,
}

try:
resp = requests.delete(url, json=data)
if 200 <= resp.status_code < 300:
print('Success')
else:
print('Error: ', str(resp.status_code), resp.text)
except Exception as e:
print('Error: ', e)

https://api.sapling.ai/api/v1/team_user_invite/<team_id>

HTTP method: DELETE

<email>: String
Email of invited user.

key: String
32-character API key. Can also be supplied via the Authorization header as a bearer token; if both are provided, the key parameter takes precedence.

Response Parameters​

Empty, HTTP status code 204.

Suppressed Emails GET​

This endpoint is used to get the list of emails that were invited but were unreachable. You must request access to this endpoint for your organization. Suppressed emails must also have a domain matching the domain of the requester.

Request Parameters​

import requests

key = '<api-key>'

url = f'https://api.sapling.ai/api/v1/organization/{organization_id}/suppressed_emails?key={key}'

try:
resp = requests.get(url)
if 200 <= resp.status_code < 300:
print('Success')
resp_json = resp.json()
print('Suppressed Emails: ', resp_json)
else:
print('Error: ', str(resp.status_code), resp.text)
except Exception as e:
print('Error: ', e)

https://api.sapling.ai/api/v1/organization/<organization_id>/suppressed_emails?key=<key>

HTTP method: GET

organization_id: String (UUID)
ID of a Sapling organization.

key: String
32-character API key. Can also be supplied via the Authorization header as a bearer token; if both are provided, the key parameter takes precedence.

Response Parameters​

JSON list of suppressed emails.

{
"suppressed_emails": ["<EMAIL1>", "<EMAIL2>"]
}