Adding & Removing Users on Kentico Kontent | OpsBlu Docs

Adding & Removing Users on Kentico Kontent

Adding & Removing Users on Kentico Kontent — setup, configuration, and best practices for Kenticokontent.

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

  1. Log in to app.kontent.ai
  2. Select the target project
  3. Click Project settings (gear icon in the sidebar)
  4. Navigate to Users
  5. Click Invite user
  6. Enter the invitee's email address
  7. 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)
  8. 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

  1. Go to Project settings > Users
  2. Find the user in the list
  3. Click the three-dot menu next to their name
  4. Select Remove from project
  5. 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_by field 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)

  1. Go to Subscription settings > Security
  2. Enable SAML Single Sign-On
  3. Configure:
    • Identity Provider Metadata URL (or upload metadata XML)
    • Default project and role for auto-provisioned users
  4. Copy the SP Metadata URL and ACS URL from Kontent.ai and configure in your IdP
  5. Map SAML attributes:
    • email -> User's email address
    • firstName -> First name
    • lastName -> Last name
  6. Test SSO login with a non-admin user
  7. 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

  1. Reassign workflow items -- Move content items from the departing user's workflow steps before removal
  2. Remove from the project via dashboard or API
  3. Rotate API keys -- If the user had access to Management API keys, regenerate them
  4. Review webhooks -- Check for webhooks the user configured pointing to external services
  5. Audit content changes -- Review the audit log for the user's recent activity
  6. Check custom roles -- If custom roles were created for the user, evaluate if they should be removed
  7. Update SSO/SCIM -- Deactivate the user in your identity provider to prevent re-authentication
  8. Review collection access -- If using collections, verify access settings are still appropriate
  9. Check language permissions -- Ensure no content in specific languages is blocked by the removal