or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-configuration.mdcomments-annotations.mdcommon-types.mddatasets.mdexceptions.mdhealth.mdindex.mdingestion.mdmedia.mdmetrics.mdmodels.mdpagination.mdprojects-organizations.mdprompts.mdscim.mdscores.mdsessions.mdtraces-observations.md

scim.mddocs/

0

# SCIM User Provisioning

1

2

The SCIM API provides SCIM 2.0-compliant user provisioning for automated organization user management. All operations require an organization-scoped API key.

3

4

## Capabilities

5

6

### ScimClient

7

8

Client for SCIM 2.0 user provisioning operations.

9

10

```java { .api }

11

/**

12

* Get SCIM Service Provider Configuration

13

* Requires organization-scoped API key

14

*

15

* @param requestOptions Optional request configuration

16

*/

17

ServiceProviderConfig getServiceProviderConfig();

18

ServiceProviderConfig getServiceProviderConfig(RequestOptions requestOptions);

19

20

/**

21

* Get SCIM Resource Types

22

* Requires organization-scoped API key

23

*

24

* @param requestOptions Optional request configuration

25

*/

26

ResourceTypesResponse getResourceTypes();

27

ResourceTypesResponse getResourceTypes(RequestOptions requestOptions);

28

29

/**

30

* Get SCIM Schemas

31

* Requires organization-scoped API key

32

*

33

* @param requestOptions Optional request configuration

34

*/

35

SchemasResponse getSchemas();

36

SchemasResponse getSchemas(RequestOptions requestOptions);

37

38

/**

39

* List users in the organization

40

* Requires organization-scoped API key

41

*

42

* @param request Optional filters (filter query, startIndex, count)

43

* @param requestOptions Optional request configuration

44

*/

45

ScimUsersListResponse listUsers();

46

ScimUsersListResponse listUsers(ListUsersRequest request);

47

ScimUsersListResponse listUsers(ListUsersRequest request, RequestOptions requestOptions);

48

49

/**

50

* Create a new user in the organization

51

* Requires organization-scoped API key

52

*

53

* @param request User definition

54

* @param requestOptions Optional request configuration

55

*/

56

ScimUser createUser(CreateUserRequest request);

57

ScimUser createUser(CreateUserRequest request, RequestOptions requestOptions);

58

59

/**

60

* Get a specific user by ID

61

* Requires organization-scoped API key

62

*

63

* @param userId User ID

64

* @param requestOptions Optional request configuration

65

*/

66

ScimUser getUser(String userId);

67

ScimUser getUser(String userId, RequestOptions requestOptions);

68

69

/**

70

* Remove a user from the organization

71

* Note: Does not delete the user entity, only removes from organization

72

* Requires organization-scoped API key

73

*

74

* @param userId User ID

75

* @param requestOptions Optional request configuration

76

*/

77

EmptyResponse deleteUser(String userId);

78

EmptyResponse deleteUser(String userId, RequestOptions requestOptions);

79

```

80

81

**Usage Examples:**

82

83

```java

84

import com.langfuse.client.LangfuseClient;

85

import com.langfuse.client.resources.scim.types.*;

86

import java.util.List;

87

88

// Use organization-scoped API key

89

LangfuseClient client = LangfuseClient.builder()

90

.url("https://cloud.langfuse.com")

91

.credentials("org-pk-...", "org-sk-...")

92

.build();

93

94

// Get service provider config

95

ServiceProviderConfig config = client.scim().getServiceProviderConfig();

96

System.out.println("Documentation: " + config.getDocumentationUri());

97

98

// List all users

99

ScimUsersListResponse users = client.scim().listUsers();

100

for (ScimUser user : users.getResources()) {

101

System.out.println(user.getUserName() + " - " + user.getDisplayName());

102

}

103

104

// Filter users

105

ListUsersRequest filterRequest = ListUsersRequest.builder()

106

.filter("userName eq \"user@example.com\"")

107

.build();

108

109

ScimUsersListResponse filtered = client.scim().listUsers(filterRequest);

110

111

// Create a user

112

CreateUserRequest userRequest = CreateUserRequest.builder()

113

.userName("newuser@example.com")

114

.emails(List.of(

115

ScimEmail.builder()

116

.value("newuser@example.com")

117

.type("work")

118

.primary(true)

119

.build()

120

))

121

.name(ScimName.builder()

122

.givenName("John")

123

.familyName("Doe")

124

.formatted("John Doe")

125

.build())

126

.displayName("John Doe")

127

.active(true)

128

.build();

129

130

ScimUser newUser = client.scim().createUser(userRequest);

131

System.out.println("Created user: " + newUser.getId());

132

133

// Get a specific user

134

ScimUser user = client.scim().getUser(newUser.getId());

135

136

// Remove user from organization

137

EmptyResponse deleteResp = client.scim().deleteUser(newUser.getId());

138

```

139

140

## Request Types

141

142

### ListUsersRequest

143

144

```java { .api }

145

/**

146

* Request parameters for listing users

147

*/

148

public final class ListUsersRequest {

149

Optional<String> getFilter(); // SCIM filter query

150

Optional<Integer> getStartIndex(); // 1-based index (default: 1)

151

Optional<Integer> getCount(); // Items per page (default: 100)

152

153

static Builder builder();

154

}

155

```

156

157

### CreateUserRequest

158

159

```java { .api }

160

/**

161

* Request for creating a user

162

*/

163

public final class CreateUserRequest {

164

String getUserName(); // Username (usually email)

165

List<ScimEmail> getEmails(); // Email addresses

166

Optional<ScimName> getName(); // Name components

167

Optional<String> getDisplayName(); // Display name

168

Optional<Boolean> getActive(); // Active status

169

170

static Builder builder();

171

}

172

```

173

174

## Response Types

175

176

### ServiceProviderConfig

177

178

```java { .api }

179

/**

180

* SCIM Service Provider Configuration

181

*/

182

public final class ServiceProviderConfig {

183

String getDocumentationUri();

184

ScimFeatureSupport getPatch();

185

BulkConfig getBulk();

186

FilterConfig getFilter();

187

ScimFeatureSupport getChangePassword();

188

ScimFeatureSupport getSort();

189

ScimFeatureSupport getEtag();

190

List<AuthenticationScheme> getAuthenticationSchemes();

191

192

static Builder builder();

193

}

194

```

195

196

### ResourceTypesResponse

197

198

```java { .api }

199

/**

200

* SCIM Resource Types

201

*/

202

public final class ResourceTypesResponse {

203

List<ResourceType> getResources();

204

205

static Builder builder();

206

}

207

```

208

209

### SchemasResponse

210

211

```java { .api }

212

/**

213

* SCIM Schemas

214

*/

215

public final class SchemasResponse {

216

List<SchemaResource> getResources();

217

218

static Builder builder();

219

}

220

```

221

222

### ScimUsersListResponse

223

224

```java { .api }

225

/**

226

* Paginated list of SCIM users

227

*/

228

public final class ScimUsersListResponse {

229

List<ScimUser> getResources();

230

int getTotalResults();

231

int getStartIndex();

232

int getItemsPerPage();

233

234

static Builder builder();

235

}

236

```

237

238

### ScimUser

239

240

```java { .api }

241

/**

242

* SCIM user resource

243

*/

244

public final class ScimUser {

245

String getId();

246

String getUserName();

247

List<ScimEmail> getEmails();

248

Optional<ScimName> getName();

249

Optional<String> getDisplayName();

250

Optional<Boolean> getActive();

251

Optional<UserMeta> getMeta();

252

253

static Builder builder();

254

}

255

```

256

257

### EmptyResponse

258

259

```java { .api }

260

/**

261

* Empty response for delete operations

262

*/

263

public final class EmptyResponse {

264

static Builder builder();

265

}

266

```

267

268

## Supporting Types

269

270

### ScimEmail

271

272

```java { .api }

273

/**

274

* Email address with type and primary flag

275

*/

276

public final class ScimEmail {

277

String getValue(); // Email address

278

Optional<String> getType(); // "work", "home", etc.

279

Optional<Boolean> getPrimary(); // Primary email flag

280

281

static Builder builder();

282

}

283

```

284

285

### ScimName

286

287

```java { .api }

288

/**

289

* User name components

290

*/

291

public final class ScimName {

292

Optional<String> getFormatted(); // Full formatted name

293

Optional<String> getFamilyName(); // Last name

294

Optional<String> getGivenName(); // First name

295

296

static Builder builder();

297

}

298

```

299

300

### UserMeta

301

302

```java { .api }

303

/**

304

* User metadata

305

*/

306

public final class UserMeta {

307

String getResourceType();

308

Optional<String> getCreated(); // ISO 8601 timestamp

309

Optional<String> getLastModified(); // ISO 8601 timestamp

310

311

static Builder builder();

312

}

313

```

314

315

### ScimFeatureSupport

316

317

```java { .api }

318

/**

319

* Feature support indicator

320

*/

321

public final class ScimFeatureSupport {

322

boolean getSupported();

323

324

static Builder builder();

325

}

326

```

327

328

### BulkConfig

329

330

```java { .api }

331

/**

332

* Bulk operation configuration

333

*/

334

public final class BulkConfig {

335

boolean getSupported();

336

int getMaxOperations();

337

int getMaxPayloadSize();

338

339

static Builder builder();

340

}

341

```

342

343

### FilterConfig

344

345

```java { .api }

346

/**

347

* Filter configuration

348

*/

349

public final class FilterConfig {

350

boolean getSupported();

351

int getMaxResults();

352

353

static Builder builder();

354

}

355

```

356

357

### AuthenticationScheme

358

359

```java { .api }

360

/**

361

* Authentication scheme details

362

*/

363

public final class AuthenticationScheme {

364

String getType();

365

String getName();

366

String getDescription();

367

Optional<String> getDocumentationUri();

368

369

static Builder builder();

370

}

371

```

372

373

### ResourceType

374

375

```java { .api }

376

/**

377

* SCIM resource type definition

378

*/

379

public final class ResourceType {

380

String getId();

381

String getName();

382

String getDescription();

383

String getEndpoint();

384

String getSchema();

385

Optional<List<SchemaExtension>> getSchemaExtensions();

386

387

static Builder builder();

388

}

389

```

390

391

### SchemaResource

392

393

```java { .api }

394

/**

395

* SCIM schema resource definition

396

*/

397

public final class SchemaResource {

398

String getId();

399

String getName();

400

String getDescription();

401

Object getAttributes(); // Schema attributes definition

402

403

static Builder builder();

404

}

405

```

406

407

## Complete SCIM Provisioning Example

408

409

```java

410

import com.langfuse.client.LangfuseClient;

411

import com.langfuse.client.resources.scim.types.*;

412

import java.util.List;

413

414

public class ScimProvisioningExample {

415

public static void main(String[] args) {

416

// Use organization-scoped API key

417

LangfuseClient client = LangfuseClient.builder()

418

.url("https://cloud.langfuse.com")

419

.credentials("org-pk-...", "org-sk-...")

420

.build();

421

422

// 1. Get SCIM service provider config

423

ServiceProviderConfig config = client.scim().getServiceProviderConfig();

424

System.out.println("SCIM documentation: " + config.getDocumentationUri());

425

System.out.println("Patch supported: " + config.getPatch().getSupported());

426

System.out.println("Bulk supported: " + config.getBulk().getSupported());

427

428

// 2. List existing users

429

ScimUsersListResponse users = client.scim().listUsers();

430

System.out.println("\nExisting users: " + users.getTotalResults());

431

432

for (ScimUser user : users.getResources()) {

433

System.out.println(" " + user.getUserName() +

434

" - Active: " + user.getActive().orElse(true));

435

}

436

437

// 3. Create new users from HR system

438

String[] newEmployees = {

439

"alice@example.com",

440

"bob@example.com",

441

"charlie@example.com"

442

};

443

444

for (String email : newEmployees) {

445

String[] parts = email.split("@")[0].split("\\.");

446

String firstName = capitalize(parts[0]);

447

String lastName = parts.length > 1 ? capitalize(parts[1]) : "";

448

449

CreateUserRequest userRequest = CreateUserRequest.builder()

450

.userName(email)

451

.emails(List.of(

452

ScimEmail.builder()

453

.value(email)

454

.type("work")

455

.primary(true)

456

.build()

457

))

458

.name(ScimName.builder()

459

.givenName(firstName)

460

.familyName(lastName)

461

.formatted(firstName + (lastName.isEmpty() ? "" : " " + lastName))

462

.build())

463

.displayName(firstName + (lastName.isEmpty() ? "" : " " + lastName))

464

.active(true)

465

.build();

466

467

try {

468

ScimUser created = client.scim().createUser(userRequest);

469

System.out.println("Created user: " + created.getUserName() +

470

" (ID: " + created.getId() + ")");

471

} catch (Exception e) {

472

System.err.println("Failed to create " + email + ": " + e.getMessage());

473

}

474

}

475

476

// 4. Filter for specific user

477

ListUsersRequest filterRequest = ListUsersRequest.builder()

478

.filter("userName eq \"alice@example.com\"")

479

.build();

480

481

ScimUsersListResponse filtered = client.scim().listUsers(filterRequest);

482

if (!filtered.getResources().isEmpty()) {

483

ScimUser alice = filtered.getResources().get(0);

484

System.out.println("\nFound user: " + alice.getDisplayName());

485

}

486

487

// 5. Paginate through large user list

488

int startIndex = 1;

489

int pageSize = 50;

490

boolean hasMore = true;

491

492

while (hasMore) {

493

ListUsersRequest pageRequest = ListUsersRequest.builder()

494

.startIndex(startIndex)

495

.count(pageSize)

496

.build();

497

498

ScimUsersListResponse page = client.scim().listUsers(pageRequest);

499

500

System.out.println("\nPage starting at " + startIndex +

501

": " + page.getResources().size() + " users");

502

503

for (ScimUser user : page.getResources()) {

504

System.out.println(" " + user.getUserName());

505

}

506

507

hasMore = startIndex + pageSize <= page.getTotalResults();

508

startIndex += pageSize;

509

}

510

511

// 6. Deactivate users (remove from organization)

512

// Note: This doesn't delete the user, just removes from organization

513

ListUsersRequest inactiveRequest = ListUsersRequest.builder()

514

.filter("active eq false")

515

.build();

516

517

ScimUsersListResponse inactive = client.scim().listUsers(inactiveRequest);

518

519

for (ScimUser user : inactive.getResources()) {

520

client.scim().deleteUser(user.getId());

521

System.out.println("Removed user from organization: " + user.getUserName());

522

}

523

}

524

525

private static String capitalize(String str) {

526

if (str == null || str.isEmpty()) return str;

527

return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase();

528

}

529

}

530

```

531

532

## SCIM Filter Examples

533

534

### Filter by Username

535

536

```java

537

ListUsersRequest request = ListUsersRequest.builder()

538

.filter("userName eq \"user@example.com\"")

539

.build();

540

```

541

542

### Filter by Active Status

543

544

```java

545

ListUsersRequest request = ListUsersRequest.builder()

546

.filter("active eq true")

547

.build();

548

```

549

550

### Filter by Email

551

552

```java

553

ListUsersRequest request = ListUsersRequest.builder()

554

.filter("emails.value eq \"user@example.com\"")

555

.build();

556

```

557

558

### Complex Filters

559

560

```java

561

// AND operator

562

String filter = "active eq true and userName co \"@example.com\"";

563

564

// OR operator

565

String filter = "userName eq \"user1@example.com\" or userName eq \"user2@example.com\"";

566

567

ListUsersRequest request = ListUsersRequest.builder()

568

.filter(filter)

569

.build();

570

```

571

572

## Best Practices

573

574

1. **Organization Keys Required**: All SCIM operations require organization-scoped API keys

575

2. **Pagination**: Use pagination for large user lists

576

3. **Filter Queries**: Use SCIM filter syntax for efficient queries

577

4. **Bulk Operations**: Check bulk support in service provider config

578

5. **Error Handling**: Handle duplicate username errors gracefully

579

6. **Active Status**: Track user active status instead of deleting

580

7. **Email Uniqueness**: Usernames and primary emails must be unique

581

8. **Integration Testing**: Test SCIM flows in development environment first

582

583

## SCIM 2.0 Compliance

584

585

Langfuse implements SCIM 2.0 core specification:

586

- Service Provider Configuration endpoint

587

- Resource Types endpoint

588

- Schemas endpoint

589

- User resource CRUD operations

590

- Filtering support

591

- Pagination support

592

593

## Related Documentation

594

595

- [Projects and Organizations](./projects-organizations.md) - Organization management

596

- [Client Configuration](./client-configuration.md) - API key configuration

597