Kentico Kontent (now rebranded as Kontent.ai) is a headless CMS with a SaaS dashboard. Team members are managed per-project through the dashboard at app.kontent.ai and the Management API. Kontent.ai uses a role-based system with environment-level permissions.
Adding Users via the Dashboard
Inviting Team Members
- Log in to app.kontent.ai
- Select the target project
- Click Project settings (gear icon in the sidebar)
- Navigate to Users
- Click Invite user
- Enter the invitee's email address
- Select a role for each environment (Production, Staging, etc.):
- Project Manager -- Full access to all content, settings, roles, and environments
- Content Manager -- Manage all content items, publish, unpublish, and manage assets
- Content Creator -- Create and edit content items; cannot publish or manage assets
- Reviewer -- View and comment on content; cannot edit
- Custom roles (available on higher-tier plans)
- Click Invite
The invited user receives an email to join the project. They must create a Kontent.ai account or log in with an existing one.
Environment-Level Permissions
Kontent.ai assigns roles per environment. A single user can have different roles across environments:
User: jsmith@example.com
├── Production: Reviewer (can only view and comment)
├── Staging: Content Creator (can edit and create)
└── Development: Project Manager (full access)
This is configured in the invitation dialog or by editing the user's permissions after they join.
Plan-Based User Limits
| Plan | Users per Project |
|---|---|
| Developer (Free) | 3 |
| Business | 15 |
| Premium | 50 |
| Enterprise | Unlimited |
Adding Users via the Management API
Kontent.ai provides a comprehensive REST Management API:
# Invite a user via the Management API
curl -X POST "https://manage.kontent.ai/v2/projects/YOUR_PROJECT_ID/users" \
-H "Authorization: Bearer YOUR_MANAGEMENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "jsmith@example.com",
"collection_groups": [
{
"collections": [{"id": "00000000-0000-0000-0000-000000000000"}],
"roles": [
{
"id": "ROLE_ID",
"languages": [{"id": "00000000-0000-0000-0000-000000000000"}]
}
]
}
]
}'
# List all users in the project
curl -s "https://manage.kontent.ai/v2/projects/YOUR_PROJECT_ID/users" \
-H "Authorization: Bearer YOUR_MANAGEMENT_API_KEY" | python3 -m json.tool
# Get available roles
curl -s "https://manage.kontent.ai/v2/projects/YOUR_PROJECT_ID/roles" \
-H "Authorization: Bearer YOUR_MANAGEMENT_API_KEY" | python3 -m json.tool
Using the JavaScript SDK
// Install: npm install @kontent-ai/management-sdk
const { ManagementClient } = require('@kontent-ai/management-sdk');
const client = new ManagementClient({
projectId: process.env.KONTENT_PROJECT_ID,
apiKey: process.env.KONTENT_MANAGEMENT_API_KEY,
});
// Invite a user
async function inviteUser(email, roleId) {
const response = await client.inviteUser()
.withData({
email: email,
collection_groups: [
{
collections: [{ id: '00000000-0000-0000-0000-000000000000' }], // Default collection
roles: [
{
id: roleId,
languages: [{ id: '00000000-0000-0000-0000-000000000000' }], // Default language
},
],
},
],
})
.toPromise();
console.log(`Invited: ${email}`, response.data);
}
// List all users
async function listUsers() {
const response = await client.listUsers().toPromise();
response.data.users.forEach(user => {
console.log(`${user.email} - ${user.status} - Last active: ${user.last_active_at || 'never'}`);
});
}
// Get all roles
async function listRoles() {
const response = await client.listRoles().toPromise();
response.data.roles.forEach(role => {
console.log(`${role.name} (${role.id}) - ${role.codename}`);
});
}
listUsers();
Creating Custom Roles (Business+ Plans)
# Create a custom role with specific permissions
curl -X POST "https://manage.kontent.ai/v2/projects/YOUR_PROJECT_ID/roles" \
-H "Authorization: Bearer YOUR_MANAGEMENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Blog Editor",
"codename": "blog_editor",
"permissions": {
"content_item": {
"read": true,
"create": true,
"update": true,
"delete": false,
"publish": true,
"unpublish": false,
"archive": true,
"create_new_version": true
},
"asset": {
"read": true,
"create": true,
"update": true,
"delete": false
},
"content_type": {
"read": true,
"manage": false
}
}
}'
Removing Users
Removing via the Dashboard
- Go to Project settings > Users
- Find the user in the list
- Click the three-dot menu next to their name
- Select Remove from project
- Confirm the removal
Removing via the Management API
# Remove a user from the project
curl -X DELETE "https://manage.kontent.ai/v2/projects/YOUR_PROJECT_ID/users/USER_ID" \
-H "Authorization: Bearer YOUR_MANAGEMENT_API_KEY"
// Remove a user via the SDK
async function removeUser(userId) {
await client.deleteUser()
.byUserId(userId)
.toPromise();
console.log(`Removed user: ${userId}`);
}
What Happens to Their Content
When you remove a Kontent.ai user:
- All content items they created remain intact -- published, draft, and scheduled items are unaffected
- Content delivered via the Delivery API continues without interruption
- The
last_modified_byfield on content items retains the user's reference - Workflow steps assigned to the user need attention -- items in the removed user's workflow step may need reassignment
- Comments on content items by the removed user are preserved
- Assets uploaded by the user remain in the asset library
- Their Kontent.ai account continues to exist but loses access to your project
- The removal is logged in the Audit Log
Checking for Assigned Workflow Items
Before removing a user, check for content items in their workflow steps:
# List content items in a specific workflow step
curl -s "https://deliver.kontent.ai/v2/projects/YOUR_PROJECT_ID/items?system.workflow_step=STEP_ID" \
-H "Authorization: Bearer YOUR_DELIVERY_API_KEY" | python3 -m json.tool
Bulk User Management
Bulk Invite Script
// bulk-invite.js -- Invite multiple users from a CSV-like array
const { ManagementClient } = require('@kontent-ai/management-sdk');
const client = new ManagementClient({
projectId: process.env.KONTENT_PROJECT_ID,
apiKey: process.env.KONTENT_MANAGEMENT_API_KEY,
});
const invites = [
{ email: 'alice@example.com', roleId: 'CONTENT_CREATOR_ROLE_ID' },
{ email: 'bob@example.com', roleId: 'CONTENT_MANAGER_ROLE_ID' },
{ email: 'carol@example.com', roleId: 'REVIEWER_ROLE_ID' },
];
async function bulkInvite() {
for (const invite of invites) {
try {
await client.inviteUser().withData({
email: invite.email,
collection_groups: [{
collections: [{ id: '00000000-0000-0000-0000-000000000000' }],
roles: [{
id: invite.roleId,
languages: [{ id: '00000000-0000-0000-0000-000000000000' }],
}],
}],
}).toPromise();
console.log(`OK: ${invite.email}`);
} catch (err) {
console.error(`FAIL: ${invite.email} -- ${err.message}`);
}
// Respect rate limits (10 requests per second)
await new Promise(r => setTimeout(r, 150));
}
}
bulkInvite();
Audit and Export Users
#!/usr/bin/env python3
"""audit_kontent_users.py -- Export all project users to CSV."""
import requests
import csv
import sys
import os
PROJECT_ID = os.environ["KONTENT_PROJECT_ID"]
API_KEY = os.environ["KONTENT_MANAGEMENT_API_KEY"]
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
# Get users
resp = requests.get(
f"https://manage.kontent.ai/v2/projects/{PROJECT_ID}/users",
headers=headers,
)
resp.raise_for_status()
users = resp.json()
# Get roles for name lookup
roles_resp = requests.get(
f"https://manage.kontent.ai/v2/projects/{PROJECT_ID}/roles",
headers=headers,
)
roles = {r["id"]: r["name"] for r in roles_resp.json().get("roles", [])}
writer = csv.writer(sys.stdout)
writer.writerow(["email", "status", "roles", "last_active"])
for user in users:
user_roles = []
for cg in user.get("collection_groups", []):
for role in cg.get("roles", []):
user_roles.append(roles.get(role["id"], role["id"]))
writer.writerow([
user.get("email"),
user.get("status"),
"; ".join(set(user_roles)),
user.get("last_active_at", "never"),
])
SSO Integration
Available Authentication Methods
- Email/password -- Standard Kontent.ai account login
- Google OAuth -- Sign in with Google
- SAML 2.0 -- Enterprise plans (Okta, Azure AD, OneLogin, Ping Identity)
Configuring SAML SSO (Enterprise)
- Go to Subscription settings > Security
- Enable SAML Single Sign-On
- Configure:
- Identity Provider Metadata URL (or upload metadata XML)
- Default project and role for auto-provisioned users
- Copy the SP Metadata URL and ACS URL from Kontent.ai and configure in your IdP
- Map SAML attributes:
email-> User's email addressfirstName-> First namelastName-> Last name
- Test SSO login with a non-admin user
- Enable Enforce SSO to require SAML authentication for all users
SCIM Provisioning (Enterprise)
Enterprise plans support SCIM 2.0 for automated user provisioning:
# SCIM endpoint for Kontent.ai
# Base URL: https://manage.kontent.ai/scim/v2
# Create a user via SCIM
curl -X POST "https://manage.kontent.ai/scim/v2/Users" \
-H "Authorization: Bearer YOUR_SCIM_TOKEN" \
-H "Content-Type: application/scim+json" \
-d '{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "jsmith@example.com",
"name": {
"givenName": "John",
"familyName": "Smith"
},
"emails": [{"value": "jsmith@example.com", "primary": true}],
"active": true
}'
SCIM integration enables automatic provisioning and deprovisioning when users are added to or removed from groups in your identity provider.
Audit Log
Kontent.ai maintains an audit log of all user and content actions:
# Query the audit log via Management API
curl -s "https://manage.kontent.ai/v2/projects/YOUR_PROJECT_ID/audit-log" \
-H "Authorization: Bearer YOUR_MANAGEMENT_API_KEY" \
| python3 -m json.tool
# Filter audit log by user
curl -s "https://manage.kontent.ai/v2/projects/YOUR_PROJECT_ID/audit-log?user_id=USER_ID" \
-H "Authorization: Bearer YOUR_MANAGEMENT_API_KEY"
Offboarding Checklist
- Reassign workflow items -- Move content items from the departing user's workflow steps before removal
- Remove from the project via dashboard or API
- Rotate API keys -- If the user had access to Management API keys, regenerate them
- Review webhooks -- Check for webhooks the user configured pointing to external services
- Audit content changes -- Review the audit log for the user's recent activity
- Check custom roles -- If custom roles were created for the user, evaluate if they should be removed
- Update SSO/SCIM -- Deactivate the user in your identity provider to prevent re-authentication
- Review collection access -- If using collections, verify access settings are still appropriate
- Check language permissions -- Ensure no content in specific languages is blocked by the removal