chub-dev 0.1.0 → 0.1.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +55 -0
  2. package/bin/chub-mcp +2 -0
  3. package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
  4. package/dist/airtable/docs/database/python/DOC.md +1735 -0
  5. package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
  6. package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
  7. package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
  8. package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
  9. package/dist/asana/docs/tasks/DOC.md +1396 -0
  10. package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
  11. package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
  12. package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
  13. package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
  14. package/dist/auth0/docs/identity/python/DOC.md +1199 -0
  15. package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
  16. package/dist/aws/docs/s3/python/DOC.md +1807 -0
  17. package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
  18. package/dist/binance/docs/trading/python/DOC.md +1454 -0
  19. package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
  20. package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
  21. package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
  22. package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
  23. package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
  24. package/dist/clerk/docs/auth/python/DOC.md +274 -0
  25. package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
  26. package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
  27. package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
  28. package/dist/cohere/docs/llm/DOC.md +1335 -0
  29. package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
  30. package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
  31. package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
  32. package/dist/deepgram/docs/speech/python/DOC.md +685 -0
  33. package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
  34. package/dist/deepl/docs/translation/python/DOC.md +944 -0
  35. package/dist/deepseek/docs/llm/DOC.md +1220 -0
  36. package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
  37. package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
  38. package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
  39. package/dist/discord/docs/bot/python/DOC.md +1130 -0
  40. package/dist/elasticsearch/docs/search/DOC.md +1634 -0
  41. package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
  42. package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
  43. package/dist/firebase/docs/auth/DOC.md +1015 -0
  44. package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
  45. package/dist/gemini/docs/genai/python/DOC.md +555 -0
  46. package/dist/github/docs/octokit/DOC.md +1560 -0
  47. package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
  48. package/dist/google/docs/bigquery/python/DOC.md +1503 -0
  49. package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
  50. package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
  51. package/dist/huggingface/docs/transformers/DOC.md +948 -0
  52. package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
  53. package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
  54. package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
  55. package/dist/jira/docs/issues/python/DOC.md +1492 -0
  56. package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
  57. package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
  58. package/dist/landingai-ade/docs/api/DOC.md +620 -0
  59. package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
  60. package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
  61. package/dist/landingai-ade/skills/SKILL.md +489 -0
  62. package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
  63. package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
  64. package/dist/linear/docs/tracker/DOC.md +1554 -0
  65. package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
  66. package/dist/livekit/docs/realtime/python/DOC.md +163 -0
  67. package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
  68. package/dist/meilisearch/docs/search/DOC.md +1241 -0
  69. package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
  70. package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
  71. package/dist/mongodb/docs/atlas/DOC.md +2041 -0
  72. package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
  73. package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
  74. package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
  75. package/dist/okta/docs/identity/python/DOC.md +1401 -0
  76. package/dist/openai/docs/chat/javascript/DOC.md +407 -0
  77. package/dist/openai/docs/chat/python/DOC.md +568 -0
  78. package/dist/paypal/docs/checkout/DOC.md +278 -0
  79. package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
  80. package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
  81. package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
  82. package/dist/plaid/docs/banking/python/DOC.md +1203 -0
  83. package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
  84. package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
  85. package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
  86. package/dist/prisma/docs/orm/python/DOC.md +1317 -0
  87. package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
  88. package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
  89. package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
  90. package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
  91. package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
  92. package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
  93. package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
  94. package/dist/redis/docs/key-value/python/DOC.md +2054 -0
  95. package/dist/registry.json +2817 -0
  96. package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
  97. package/dist/resend/docs/email/DOC.md +1271 -0
  98. package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
  99. package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
  100. package/dist/search-index.json +1 -0
  101. package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
  102. package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
  103. package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
  104. package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
  105. package/dist/shopify/docs/storefront/DOC.md +457 -0
  106. package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
  107. package/dist/slack/docs/workspace/python/DOC.md +271 -0
  108. package/dist/square/docs/payments/javascript/DOC.md +1855 -0
  109. package/dist/square/docs/payments/python/DOC.md +1728 -0
  110. package/dist/stripe/docs/api/DOC.md +1727 -0
  111. package/dist/stripe/docs/payments/DOC.md +1726 -0
  112. package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
  113. package/dist/stytch/docs/auth/python/DOC.md +1962 -0
  114. package/dist/supabase/docs/client/DOC.md +1606 -0
  115. package/dist/twilio/docs/messaging/python/DOC.md +469 -0
  116. package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
  117. package/dist/vercel/docs/platform/DOC.md +1940 -0
  118. package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
  119. package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
  120. package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
  121. package/dist/zendesk/docs/support/python/DOC.md +2297 -0
  122. package/package.json +22 -6
  123. package/skills/get-api-docs/SKILL.md +84 -0
  124. package/src/commands/annotate.js +83 -0
  125. package/src/commands/build.js +12 -1
  126. package/src/commands/feedback.js +150 -0
  127. package/src/commands/get.js +83 -42
  128. package/src/commands/search.js +7 -0
  129. package/src/index.js +43 -17
  130. package/src/lib/analytics.js +90 -0
  131. package/src/lib/annotations.js +57 -0
  132. package/src/lib/bm25.js +170 -0
  133. package/src/lib/cache.js +69 -6
  134. package/src/lib/config.js +8 -3
  135. package/src/lib/identity.js +99 -0
  136. package/src/lib/registry.js +103 -20
  137. package/src/lib/telemetry.js +86 -0
  138. package/src/mcp/server.js +177 -0
  139. package/src/mcp/tools.js +251 -0
@@ -0,0 +1,1171 @@
1
+ ---
2
+ name: identity
3
+ description: "Okta Node.js SDK coding guidelines for the Okta Management API using official libraries"
4
+ metadata:
5
+ languages: "javascript"
6
+ versions: "7.3.0"
7
+ updated-on: "2026-03-02"
8
+ source: maintainer
9
+ tags: "okta,identity,sso,oauth,authentication"
10
+ ---
11
+
12
+ # Okta Node.js SDK Coding Guidelines
13
+
14
+ You are an Okta API coding expert. Help me with writing code using the Okta Management API calling the official libraries and SDKs.
15
+
16
+ You can find the official SDK documentation and code samples here:
17
+ https://developer.okta.com/docs/reference/api/users/
18
+ https://github.com/okta/okta-sdk-nodejs
19
+
20
+ ## Golden Rule: Use the Correct and Current SDK
21
+
22
+ Always use the official Okta Node.js SDK to interact with the Okta Management API. This is the standard library for all Okta Management API interactions. Do not use deprecated packages or the authentication SDK for management tasks.
23
+
24
+ - **Library Name:** Okta Node.js SDK
25
+ - **NPM Package:** `@okta/okta-sdk-nodejs`
26
+ - **Current Version:** 7.3.0
27
+ - **Authentication SDK (Different Use Case):** `@okta/okta-auth-js` - Only for end-user authentication flows, NOT for management API
28
+
29
+ **Installation:**
30
+
31
+ - **Correct:** `npm install @okta/okta-sdk-nodejs`
32
+
33
+ **APIs and Usage:**
34
+
35
+ - **Correct:** `const okta = require('@okta/okta-sdk-nodejs')`
36
+ - **Correct:** `const client = new okta.Client({ orgUrl, token })`
37
+ - **Correct:** `await client.userApi.createUser({ body: newUser })`
38
+ - **Correct:** `await client.groupApi.createGroup({ group: newGroup })`
39
+ - **Correct:** `await client.applicationApi.createApplication({ application })`
40
+ - **Incorrect:** Using `@okta/okta-auth-js` for management operations
41
+ - **Incorrect:** Direct HTTP calls without SDK
42
+
43
+ ## System Requirements
44
+
45
+ The Okta Node.js SDK requires:
46
+ - Node.js v12.0.0 or higher
47
+ - An Okta organization URL
48
+ - An API token or OAuth 2.0 credentials
49
+
50
+ ## Initialization and API Authentication
51
+
52
+ The `@okta/okta-sdk-nodejs` library requires creating a `Client` instance for all API calls.
53
+
54
+ ### API Token Authentication (Simple)
55
+
56
+ ```javascript
57
+ const okta = require('@okta/okta-sdk-nodejs');
58
+
59
+ const client = new okta.Client({
60
+ orgUrl: 'https://dev-1234.okta.com',
61
+ token: process.env.OKTA_API_TOKEN
62
+ });
63
+ ```
64
+
65
+ ### OAuth 2.0 Private Key Authentication (Recommended for Service Apps)
66
+
67
+ When using OAuth 2.0 with private key authentication, you don't need an API token. The SDK automatically requests access tokens.
68
+
69
+ ```javascript
70
+ const okta = require('@okta/okta-sdk-nodejs');
71
+
72
+ const client = new okta.Client({
73
+ orgUrl: 'https://dev-1234.okta.com',
74
+ authorizationMode: 'PrivateKey',
75
+ clientId: process.env.OKTA_CLIENT_ID,
76
+ scopes: ['okta.users.manage', 'okta.groups.manage'],
77
+ privateKey: process.env.OKTA_PRIVATE_KEY, // JWK JSON string or PEM format
78
+ keyId: process.env.OKTA_KEY_ID // Optional if kid is in JWK
79
+ });
80
+ ```
81
+
82
+ ### Private Key Formats
83
+
84
+ The `privateKey` parameter accepts:
85
+
86
+ - **JWK (JSON Web Key) as string:**
87
+ ```javascript
88
+ privateKey: '{"kty":"RSA","kid":"my-key-id","n":"...","e":"AQAB","d":"..."}'
89
+ ```
90
+
91
+ - **JWK as object:**
92
+ ```javascript
93
+ privateKey: {
94
+ kty: 'RSA',
95
+ kid: 'my-key-id',
96
+ n: '...',
97
+ e: 'AQAB',
98
+ d: '...'
99
+ }
100
+ ```
101
+
102
+ - **PEM format:**
103
+ ```javascript
104
+ privateKey: `-----BEGIN PRIVATE KEY-----
105
+ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...
106
+ -----END PRIVATE KEY-----`
107
+ ```
108
+
109
+ ## User Management
110
+
111
+ ### Create a User
112
+
113
+ Create a new user with profile information and password:
114
+
115
+ ```javascript
116
+ const okta = require('@okta/okta-sdk-nodejs');
117
+ const client = new okta.Client({ orgUrl, token });
118
+
119
+ async function createUser() {
120
+ const newUser = {
121
+ profile: {
122
+ firstName: 'John',
123
+ lastName: 'Doe',
124
+ email: 'john.doe@example.com',
125
+ login: 'john.doe@example.com'
126
+ },
127
+ credentials: {
128
+ password: {
129
+ value: 'SecurePassword123!'
130
+ }
131
+ }
132
+ };
133
+
134
+ const user = await client.userApi.createUser({ body: newUser });
135
+ console.log('Created user:', user.id);
136
+ return user;
137
+ }
138
+ ```
139
+
140
+ ### Create User with Activation
141
+
142
+ Create and automatically activate a user:
143
+
144
+ ```javascript
145
+ async function createAndActivateUser() {
146
+ const newUser = {
147
+ profile: {
148
+ firstName: 'Jane',
149
+ lastName: 'Smith',
150
+ email: 'jane.smith@example.com',
151
+ login: 'jane.smith@example.com'
152
+ },
153
+ credentials: {
154
+ password: {
155
+ value: 'SecurePassword123!'
156
+ }
157
+ }
158
+ };
159
+
160
+ const user = await client.userApi.createUser({
161
+ body: newUser,
162
+ activate: true
163
+ });
164
+
165
+ console.log('Created and activated user:', user.id);
166
+ return user;
167
+ }
168
+ ```
169
+
170
+ ### Get a User
171
+
172
+ Retrieve a user by ID or login:
173
+
174
+ ```javascript
175
+ async function getUser() {
176
+ // By user ID
177
+ let user = await client.userApi.getUser({
178
+ userId: 'ausmvdt5xg8wRVI1d0g3'
179
+ });
180
+
181
+ // By login email
182
+ user = await client.userApi.getUser({
183
+ userId: 'john.doe@example.com'
184
+ });
185
+
186
+ console.log('User:', user.profile.firstName, user.profile.lastName);
187
+ return user;
188
+ }
189
+ ```
190
+
191
+ ### List All Users
192
+
193
+ Iterate through all users in your organization:
194
+
195
+ ```javascript
196
+ async function listAllUsers() {
197
+ const collection = await client.userApi.listUsers();
198
+
199
+ // Using .each() method
200
+ await collection.each(user => {
201
+ console.log(`${user.profile.firstName} ${user.profile.lastName} (${user.profile.email})`);
202
+ });
203
+ }
204
+ ```
205
+
206
+ ### List Users with Async Iteration
207
+
208
+ ```javascript
209
+ async function listUsersAsyncIteration() {
210
+ const collection = await client.userApi.listUsers();
211
+
212
+ // Using for...await
213
+ for await (let user of collection) {
214
+ console.log(`User ID: ${user.id}, Name: ${user.profile.firstName} ${user.profile.lastName}`);
215
+ }
216
+ }
217
+ ```
218
+
219
+ ### Search Users by Query
220
+
221
+ Search users using simple query string:
222
+
223
+ ```javascript
224
+ async function searchUsersByName() {
225
+ const collection = await client.userApi.listUsers({
226
+ q: 'Robert'
227
+ });
228
+
229
+ for await (let user of collection) {
230
+ console.log('Found user:', user.profile.email);
231
+ }
232
+ }
233
+ ```
234
+
235
+ ### Search Users with SCIM Filter
236
+
237
+ Use SCIM expressions for precise filtering:
238
+
239
+ ```javascript
240
+ async function searchUsersWithFilter() {
241
+ // SCIM filter for exact match
242
+ const collection = await client.userApi.listUsers({
243
+ search: 'profile.nickName eq "bobby"'
244
+ });
245
+
246
+ for await (let user of collection) {
247
+ console.log('Found user:', user.profile.email);
248
+ }
249
+ }
250
+ ```
251
+
252
+ ### Filter Users by Time
253
+
254
+ Find users updated after a specific time:
255
+
256
+ ```javascript
257
+ async function findRecentlyUpdatedUsers() {
258
+ const collection = await client.userApi.listUsers({
259
+ filter: 'lastUpdated gt "2025-01-01T00:00:00.000Z"'
260
+ });
261
+
262
+ for await (let user of collection) {
263
+ console.log('Recently updated:', user.profile.email, 'at', user.lastUpdated);
264
+ }
265
+ }
266
+ ```
267
+
268
+ ### Update a User
269
+
270
+ Modify user profile information:
271
+
272
+ ```javascript
273
+ async function updateUser(userId) {
274
+ const user = await client.userApi.getUser({ userId });
275
+
276
+ // Update profile fields
277
+ user.profile.nickName = 'Johnny';
278
+ user.profile.mobilePhone = '+1-555-123-4567';
279
+
280
+ await client.userApi.updateUser({
281
+ userId: user.id,
282
+ user: user
283
+ });
284
+
285
+ console.log('User updated successfully');
286
+ }
287
+ ```
288
+
289
+ ### Partial Update a User
290
+
291
+ Update specific fields without retrieving the full user object:
292
+
293
+ ```javascript
294
+ async function partialUpdateUser(userId) {
295
+ const updates = {
296
+ profile: {
297
+ nickName: 'JD',
298
+ department: 'Engineering'
299
+ }
300
+ };
301
+
302
+ await client.userApi.updateUser({
303
+ userId: userId,
304
+ user: updates
305
+ });
306
+
307
+ console.log('User partially updated');
308
+ }
309
+ ```
310
+
311
+ ### Deactivate a User
312
+
313
+ Deactivate a user account:
314
+
315
+ ```javascript
316
+ async function deactivateUser(userId) {
317
+ await client.userApi.deactivateUser({ userId });
318
+ console.log('User deactivated');
319
+ }
320
+ ```
321
+
322
+ ### Delete a User
323
+
324
+ Permanently delete a user (must be deactivated first):
325
+
326
+ ```javascript
327
+ async function deleteUser(userId) {
328
+ // First deactivate
329
+ await client.userApi.deactivateUser({ userId });
330
+
331
+ // Then delete
332
+ await client.userApi.deleteUser({ userId });
333
+
334
+ console.log('User deleted permanently');
335
+ }
336
+ ```
337
+
338
+ ### Reactivate a User
339
+
340
+ Reactivate a previously deactivated user:
341
+
342
+ ```javascript
343
+ async function reactivateUser(userId) {
344
+ await client.userApi.activateUser({
345
+ userId: userId,
346
+ sendEmail: false
347
+ });
348
+
349
+ console.log('User reactivated');
350
+ }
351
+ ```
352
+
353
+ ### Suspend and Unsuspend User
354
+
355
+ Temporarily suspend a user:
356
+
357
+ ```javascript
358
+ async function suspendUser(userId) {
359
+ await client.userApi.suspendUser({ userId });
360
+ console.log('User suspended');
361
+ }
362
+
363
+ async function unsuspendUser(userId) {
364
+ await client.userApi.unsuspendUser({ userId });
365
+ console.log('User unsuspended');
366
+ }
367
+ ```
368
+
369
+ ### Reset User Password
370
+
371
+ Send a password reset email:
372
+
373
+ ```javascript
374
+ async function resetUserPassword(userId) {
375
+ await client.userApi.resetPassword({
376
+ userId: userId,
377
+ sendEmail: true
378
+ });
379
+
380
+ console.log('Password reset email sent');
381
+ }
382
+ ```
383
+
384
+ ### Expire User Password
385
+
386
+ Force a user to change password on next login:
387
+
388
+ ```javascript
389
+ async function expireUserPassword(userId) {
390
+ const user = await client.userApi.expirePassword({
391
+ userId: userId
392
+ });
393
+
394
+ console.log('Password expired for user:', user.id);
395
+ }
396
+ ```
397
+
398
+ ## Group Management
399
+
400
+ ### Create a Group
401
+
402
+ Create a new group:
403
+
404
+ ```javascript
405
+ async function createGroup() {
406
+ const newGroup = {
407
+ profile: {
408
+ name: 'Engineering Team',
409
+ description: 'All engineering department members'
410
+ }
411
+ };
412
+
413
+ const group = await client.groupApi.createGroup({ group: newGroup });
414
+ console.log('Created group:', group.id);
415
+ return group;
416
+ }
417
+ ```
418
+
419
+ ### Get a Group
420
+
421
+ Retrieve a group by ID:
422
+
423
+ ```javascript
424
+ async function getGroup(groupId) {
425
+ const group = await client.groupApi.getGroup({ groupId });
426
+ console.log('Group:', group.profile.name);
427
+ return group;
428
+ }
429
+ ```
430
+
431
+ ### List All Groups
432
+
433
+ List all groups in the organization:
434
+
435
+ ```javascript
436
+ async function listAllGroups() {
437
+ const collection = await client.groupApi.listGroups();
438
+
439
+ for await (let group of collection) {
440
+ console.log(`Group: ${group.profile.name} (${group.id})`);
441
+ }
442
+ }
443
+ ```
444
+
445
+ ### Search Groups by Name
446
+
447
+ Search for groups matching a query:
448
+
449
+ ```javascript
450
+ async function searchGroups() {
451
+ const collection = await client.groupApi.listGroups({
452
+ q: 'Engineering'
453
+ });
454
+
455
+ for await (let group of collection) {
456
+ console.log('Found group:', group.profile.name);
457
+ }
458
+ }
459
+ ```
460
+
461
+ ### Update a Group
462
+
463
+ Update group profile information:
464
+
465
+ ```javascript
466
+ async function updateGroup(groupId) {
467
+ const group = await client.groupApi.getGroup({ groupId });
468
+
469
+ group.profile.description = 'Updated description';
470
+
471
+ await client.groupApi.updateGroup({
472
+ groupId: group.id,
473
+ group: group
474
+ });
475
+
476
+ console.log('Group updated');
477
+ }
478
+ ```
479
+
480
+ ### Delete a Group
481
+
482
+ Delete a group:
483
+
484
+ ```javascript
485
+ async function deleteGroup(groupId) {
486
+ await client.groupApi.deleteGroup({ groupId });
487
+ console.log('Group deleted');
488
+ }
489
+ ```
490
+
491
+ ### Assign User to Group
492
+
493
+ Add a user to a group:
494
+
495
+ ```javascript
496
+ async function assignUserToGroup(groupId, userId) {
497
+ await client.groupApi.assignUserToGroup({
498
+ groupId: groupId,
499
+ userId: userId
500
+ });
501
+
502
+ console.log(`User ${userId} added to group ${groupId}`);
503
+ }
504
+ ```
505
+
506
+ ### Remove User from Group
507
+
508
+ Remove a user from a group:
509
+
510
+ ```javascript
511
+ async function removeUserFromGroup(groupId, userId) {
512
+ await client.groupApi.unassignUserFromGroup({
513
+ groupId: groupId,
514
+ userId: userId
515
+ });
516
+
517
+ console.log(`User ${userId} removed from group ${groupId}`);
518
+ }
519
+ ```
520
+
521
+ ### List Group Members
522
+
523
+ Get all users in a group:
524
+
525
+ ```javascript
526
+ async function listGroupMembers(groupId) {
527
+ const collection = await client.groupApi.listGroupUsers({ groupId });
528
+
529
+ for await (let user of collection) {
530
+ console.log(`Member: ${user.profile.firstName} ${user.profile.lastName}`);
531
+ }
532
+ }
533
+ ```
534
+
535
+ ### List User's Groups
536
+
537
+ Get all groups a user belongs to:
538
+
539
+ ```javascript
540
+ async function listUserGroups(userId) {
541
+ const collection = await client.userApi.listUserGroups({ userId });
542
+
543
+ for await (let group of collection) {
544
+ console.log(`User is in group: ${group.profile.name}`);
545
+ }
546
+ }
547
+ ```
548
+
549
+ ## Application Management
550
+
551
+ ### Create a Basic Auth Application
552
+
553
+ ```javascript
554
+ async function createBasicAuthApp() {
555
+ const application = {
556
+ name: 'template_basic_auth',
557
+ label: 'Sample Basic Auth App',
558
+ signOnMode: 'BASIC_AUTH',
559
+ settings: {
560
+ app: {
561
+ url: 'https://example.com/auth.htm',
562
+ authURL: 'https://example.com/login.html'
563
+ }
564
+ }
565
+ };
566
+
567
+ const app = await client.applicationApi.createApplication({
568
+ application: application
569
+ });
570
+
571
+ console.log('Created application:', app.id);
572
+ return app;
573
+ }
574
+ ```
575
+
576
+ ### Create a SAML 2.0 Application
577
+
578
+ ```javascript
579
+ async function createSAMLApp() {
580
+ const application = {
581
+ name: 'template_saml_2_0',
582
+ label: 'SAML 2.0 App',
583
+ signOnMode: 'SAML_2_0',
584
+ settings: {
585
+ signOn: {
586
+ defaultRelayState: '',
587
+ ssoAcsUrl: 'https://example.com/sso/saml',
588
+ recipient: 'https://example.com/sso/saml',
589
+ destination: 'https://example.com/sso/saml',
590
+ audience: 'https://example.com',
591
+ idpIssuer: 'http://www.okta.com/${org.externalKey}',
592
+ subjectNameIdTemplate: '${user.userName}',
593
+ subjectNameIdFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
594
+ responseSigned: true,
595
+ assertionSigned: true,
596
+ signatureAlgorithm: 'RSA_SHA256',
597
+ digestAlgorithm: 'SHA256',
598
+ honorForceAuthn: true,
599
+ authnContextClassRef: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
600
+ }
601
+ }
602
+ };
603
+
604
+ const app = await client.applicationApi.createApplication({
605
+ application: application
606
+ });
607
+
608
+ console.log('Created SAML application:', app.id);
609
+ return app;
610
+ }
611
+ ```
612
+
613
+ ### Create an OAuth 2.0 Application
614
+
615
+ ```javascript
616
+ async function createOAuthApp() {
617
+ const application = {
618
+ name: 'oidc_client',
619
+ label: 'OAuth 2.0 App',
620
+ signOnMode: 'OPENID_CONNECT',
621
+ credentials: {
622
+ oauthClient: {
623
+ token_endpoint_auth_method: 'client_secret_post'
624
+ }
625
+ },
626
+ settings: {
627
+ oauthClient: {
628
+ client_uri: 'https://example.com',
629
+ logo_uri: 'https://example.com/logo.png',
630
+ redirect_uris: ['https://example.com/oauth/callback'],
631
+ response_types: ['code'],
632
+ grant_types: ['authorization_code', 'refresh_token'],
633
+ application_type: 'web'
634
+ }
635
+ }
636
+ };
637
+
638
+ const app = await client.applicationApi.createApplication({
639
+ application: application
640
+ });
641
+
642
+ console.log('Created OAuth app:', app.id);
643
+ console.log('Client ID:', app.credentials.oauthClient.client_id);
644
+ console.log('Client Secret:', app.credentials.oauthClient.client_secret);
645
+ return app;
646
+ }
647
+ ```
648
+
649
+ ### Get an Application
650
+
651
+ Retrieve an application by ID:
652
+
653
+ ```javascript
654
+ async function getApplication(appId) {
655
+ const app = await client.applicationApi.getApplication({
656
+ appId: appId
657
+ });
658
+
659
+ console.log('Application:', app.label);
660
+ return app;
661
+ }
662
+ ```
663
+
664
+ ### List All Applications
665
+
666
+ ```javascript
667
+ async function listAllApplications() {
668
+ const collection = await client.applicationApi.listApplications();
669
+
670
+ for await (let app of collection) {
671
+ console.log(`App: ${app.label} (${app.id})`);
672
+ }
673
+ }
674
+ ```
675
+
676
+ ### Update an Application
677
+
678
+ ```javascript
679
+ async function updateApplication(appId) {
680
+ const app = await client.applicationApi.getApplication({ appId });
681
+
682
+ app.label = 'Updated Application Name';
683
+
684
+ await client.applicationApi.updateApplication({
685
+ appId: app.id,
686
+ application: app
687
+ });
688
+
689
+ console.log('Application updated');
690
+ }
691
+ ```
692
+
693
+ ### Delete an Application
694
+
695
+ ```javascript
696
+ async function deleteApplication(appId) {
697
+ await client.applicationApi.deactivateApplication({ appId });
698
+ await client.applicationApi.deleteApplication({ appId });
699
+ console.log('Application deleted');
700
+ }
701
+ ```
702
+
703
+ ### Assign User to Application
704
+
705
+ ```javascript
706
+ async function assignUserToApplication(appId, userId) {
707
+ const appUser = await client.applicationApi.assignUserToApplication({
708
+ appId: appId,
709
+ appUser: {
710
+ id: userId
711
+ }
712
+ });
713
+
714
+ console.log('User assigned to application:', appUser.id);
715
+ return appUser;
716
+ }
717
+ ```
718
+
719
+ ### Assign User with Profile to Application
720
+
721
+ ```javascript
722
+ async function assignUserWithProfile(appId, userId) {
723
+ const appUser = await client.applicationApi.assignUserToApplication({
724
+ appId: appId,
725
+ appUser: {
726
+ id: userId,
727
+ credentials: {
728
+ userName: 'user@example.com',
729
+ password: { value: 'AppSpecificPassword123!' }
730
+ },
731
+ profile: {
732
+ role: 'Admin',
733
+ department: 'Engineering'
734
+ }
735
+ }
736
+ });
737
+
738
+ console.log('User assigned with profile');
739
+ return appUser;
740
+ }
741
+ ```
742
+
743
+ ### Remove User from Application
744
+
745
+ ```javascript
746
+ async function removeUserFromApplication(appId, userId) {
747
+ await client.applicationApi.unassignUserFromApplication({
748
+ appId: appId,
749
+ userId: userId
750
+ });
751
+
752
+ console.log('User removed from application');
753
+ }
754
+ ```
755
+
756
+ ### Assign Group to Application
757
+
758
+ ```javascript
759
+ async function assignGroupToApplication(appId, groupId) {
760
+ const assignment = await client.applicationApi.assignGroupToApplication({
761
+ appId: appId,
762
+ groupId: groupId,
763
+ applicationGroupAssignment: {}
764
+ });
765
+
766
+ console.log('Group assigned to application');
767
+ return assignment;
768
+ }
769
+ ```
770
+
771
+ ### Remove Group from Application
772
+
773
+ ```javascript
774
+ async function removeGroupFromApplication(appId, groupId) {
775
+ await client.applicationApi.unassignApplicationFromGroup({
776
+ appId: appId,
777
+ groupId: groupId
778
+ });
779
+
780
+ console.log('Group removed from application');
781
+ }
782
+ ```
783
+
784
+ ### List Application Users
785
+
786
+ Get all users assigned to an application:
787
+
788
+ ```javascript
789
+ async function listApplicationUsers(appId) {
790
+ const collection = await client.applicationApi.listApplicationUsers({
791
+ appId: appId
792
+ });
793
+
794
+ for await (let appUser of collection) {
795
+ console.log(`User ${appUser.id} assigned to app`);
796
+ }
797
+ }
798
+ ```
799
+
800
+ ### List Application Groups
801
+
802
+ Get all groups assigned to an application:
803
+
804
+ ```javascript
805
+ async function listApplicationGroups(appId) {
806
+ const collection = await client.applicationApi.listApplicationGroupAssignments({
807
+ appId: appId
808
+ });
809
+
810
+ for await (let assignment of collection) {
811
+ console.log(`Group ${assignment.id} assigned to app`);
812
+ }
813
+ }
814
+ ```
815
+
816
+ ## Authentication and Sessions
817
+
818
+ ### List Active User Sessions
819
+
820
+ ```javascript
821
+ async function listUserSessions(userId) {
822
+ const collection = await client.userApi.listUserSessions({ userId });
823
+
824
+ for await (let session of collection) {
825
+ console.log(`Session ID: ${session.id}, Created: ${session.createdAt}`);
826
+ }
827
+ }
828
+ ```
829
+
830
+ ### Clear User Sessions
831
+
832
+ Clear all sessions for a user:
833
+
834
+ ```javascript
835
+ async function clearUserSessions(userId) {
836
+ await client.userApi.clearUserSessions({ userId });
837
+ console.log('All user sessions cleared');
838
+ }
839
+ ```
840
+
841
+ ## Error Handling
842
+
843
+ Always wrap API calls in try-catch blocks:
844
+
845
+ ```javascript
846
+ async function handleErrors() {
847
+ try {
848
+ const user = await client.userApi.getUser({
849
+ userId: 'nonexistent@example.com'
850
+ });
851
+ } catch (error) {
852
+ if (error.status === 404) {
853
+ console.error('User not found');
854
+ } else if (error.status === 401) {
855
+ console.error('Authentication failed - check your API token');
856
+ } else if (error.status === 403) {
857
+ console.error('Forbidden - insufficient permissions');
858
+ } else if (error.status === 429) {
859
+ console.error('Rate limit exceeded');
860
+ } else {
861
+ console.error('API Error:', error.message);
862
+ }
863
+ }
864
+ }
865
+ ```
866
+
867
+ ### Comprehensive Error Handling Pattern
868
+
869
+ ```javascript
870
+ async function createUserWithErrorHandling(userData) {
871
+ try {
872
+ const newUser = {
873
+ profile: {
874
+ firstName: userData.firstName,
875
+ lastName: userData.lastName,
876
+ email: userData.email,
877
+ login: userData.email
878
+ },
879
+ credentials: {
880
+ password: {
881
+ value: userData.password
882
+ }
883
+ }
884
+ };
885
+
886
+ const user = await client.userApi.createUser({ body: newUser });
887
+ console.log('User created successfully:', user.id);
888
+ return { success: true, user };
889
+
890
+ } catch (error) {
891
+ console.error('Error creating user:', error.message);
892
+
893
+ if (error.status === 400) {
894
+ console.error('Bad request - check user data format');
895
+ if (error.body && error.body.errorCauses) {
896
+ error.body.errorCauses.forEach(cause => {
897
+ console.error('Error cause:', cause.errorSummary);
898
+ });
899
+ }
900
+ } else if (error.status === 401) {
901
+ console.error('Authentication failed');
902
+ } else if (error.status === 403) {
903
+ console.error('Forbidden - insufficient permissions');
904
+ } else if (error.status === 409) {
905
+ console.error('Conflict - user already exists');
906
+ } else if (error.status === 429) {
907
+ console.error('Rate limit exceeded - retry after delay');
908
+ } else if (error.status >= 500) {
909
+ console.error('Server error - Okta service issue');
910
+ }
911
+
912
+ return { success: false, error: error.message };
913
+ }
914
+ }
915
+ ```
916
+
917
+ ## Pagination
918
+
919
+ Collections automatically handle pagination. Use `limit` to control page size:
920
+
921
+ ```javascript
922
+ async function paginateUsers() {
923
+ const collection = await client.userApi.listUsers({
924
+ limit: 20 // 20 users per page
925
+ });
926
+
927
+ for await (let user of collection) {
928
+ // SDK automatically fetches next pages
929
+ console.log(user.profile.email);
930
+ }
931
+ }
932
+ ```
933
+
934
+ ### Manual Pagination with After Parameter
935
+
936
+ ```javascript
937
+ async function manualPagination() {
938
+ let after;
939
+ let pageCount = 0;
940
+
941
+ do {
942
+ const response = await client.userApi.listUsers({
943
+ limit: 10,
944
+ after: after
945
+ });
946
+
947
+ const users = response.users || [];
948
+ console.log(`Page ${++pageCount}: ${users.length} users`);
949
+
950
+ users.forEach(user => {
951
+ console.log(' -', user.profile.email);
952
+ });
953
+
954
+ // Check if there's a next page
955
+ after = response.nextPage ? response.nextPage.after : null;
956
+
957
+ } while (after);
958
+ }
959
+ ```
960
+
961
+ ## Rate Limiting
962
+
963
+ The SDK automatically handles rate limiting with retry logic. Be aware of Okta rate limits:
964
+
965
+ - Most endpoints: 600 requests per minute
966
+ - Authentication endpoints: Varies by org tier
967
+ - Concurrent requests: Limited per org
968
+
969
+ ```javascript
970
+ async function bulkOperationWithRateLimit() {
971
+ const users = []; // Large array of users to create
972
+
973
+ for (const userData of users) {
974
+ try {
975
+ const user = await client.userApi.createUser({ body: userData });
976
+ console.log('Created user:', user.id);
977
+
978
+ // Optional: Add delay between requests
979
+ await new Promise(resolve => setTimeout(resolve, 100));
980
+
981
+ } catch (error) {
982
+ if (error.status === 429) {
983
+ console.log('Rate limit hit, waiting before retry...');
984
+ await new Promise(resolve => setTimeout(resolve, 5000));
985
+ // Retry logic here
986
+ }
987
+ }
988
+ }
989
+ }
990
+ ```
991
+
992
+ ## Working with Custom User Attributes
993
+
994
+ ### Create User with Custom Attributes
995
+
996
+ ```javascript
997
+ async function createUserWithCustomAttributes() {
998
+ const newUser = {
999
+ profile: {
1000
+ firstName: 'John',
1001
+ lastName: 'Doe',
1002
+ email: 'john.doe@example.com',
1003
+ login: 'john.doe@example.com',
1004
+ // Custom attributes (must be defined in user schema first)
1005
+ employeeId: 'EMP-12345',
1006
+ department: 'Engineering',
1007
+ costCenter: 'CC-100'
1008
+ },
1009
+ credentials: {
1010
+ password: {
1011
+ value: 'SecurePassword123!'
1012
+ }
1013
+ }
1014
+ };
1015
+
1016
+ const user = await client.userApi.createUser({ body: newUser });
1017
+ console.log('Created user with custom attributes:', user.id);
1018
+ }
1019
+ ```
1020
+
1021
+ ## Complete Example Application
1022
+
1023
+ ```javascript
1024
+ const okta = require('@okta/okta-sdk-nodejs');
1025
+
1026
+ // Initialize client
1027
+ const client = new okta.Client({
1028
+ orgUrl: process.env.OKTA_ORG_URL,
1029
+ token: process.env.OKTA_API_TOKEN
1030
+ });
1031
+
1032
+ async function main() {
1033
+ try {
1034
+ // Create a user
1035
+ const newUser = {
1036
+ profile: {
1037
+ firstName: 'Alice',
1038
+ lastName: 'Johnson',
1039
+ email: 'alice.johnson@example.com',
1040
+ login: 'alice.johnson@example.com'
1041
+ },
1042
+ credentials: {
1043
+ password: { value: 'SecurePassword123!' }
1044
+ }
1045
+ };
1046
+
1047
+ const user = await client.userApi.createUser({
1048
+ body: newUser,
1049
+ activate: true
1050
+ });
1051
+ console.log('Created user:', user.id);
1052
+
1053
+ // Create a group
1054
+ const newGroup = {
1055
+ profile: {
1056
+ name: 'Project Team Alpha',
1057
+ description: 'Members of Project Alpha'
1058
+ }
1059
+ };
1060
+
1061
+ const group = await client.groupApi.createGroup({ group: newGroup });
1062
+ console.log('Created group:', group.id);
1063
+
1064
+ // Add user to group
1065
+ await client.groupApi.assignUserToGroup({
1066
+ groupId: group.id,
1067
+ userId: user.id
1068
+ });
1069
+ console.log('User added to group');
1070
+
1071
+ // Create an application
1072
+ const application = {
1073
+ name: 'template_basic_auth',
1074
+ label: 'Team Application',
1075
+ signOnMode: 'BASIC_AUTH',
1076
+ settings: {
1077
+ app: {
1078
+ url: 'https://example.com/app',
1079
+ authURL: 'https://example.com/login'
1080
+ }
1081
+ }
1082
+ };
1083
+
1084
+ const app = await client.applicationApi.createApplication({
1085
+ application: application
1086
+ });
1087
+ console.log('Created application:', app.id);
1088
+
1089
+ // Assign group to application
1090
+ await client.applicationApi.assignGroupToApplication({
1091
+ appId: app.id,
1092
+ groupId: group.id,
1093
+ applicationGroupAssignment: {}
1094
+ });
1095
+ console.log('Group assigned to application');
1096
+
1097
+ // List all users in the group
1098
+ console.log('\nGroup members:');
1099
+ const members = await client.groupApi.listGroupUsers({ groupId: group.id });
1100
+ for await (let member of members) {
1101
+ console.log(` - ${member.profile.firstName} ${member.profile.lastName}`);
1102
+ }
1103
+
1104
+ } catch (error) {
1105
+ console.error('Error:', error.message);
1106
+ if (error.status) {
1107
+ console.error('Status:', error.status);
1108
+ }
1109
+ }
1110
+ }
1111
+
1112
+ main();
1113
+ ```
1114
+
1115
+ ## Environment Variables Setup
1116
+
1117
+ Create a `.env` file for configuration:
1118
+
1119
+ ```bash
1120
+ OKTA_ORG_URL=https://dev-1234567.okta.com
1121
+ OKTA_API_TOKEN=your_api_token_here
1122
+ ```
1123
+
1124
+ Load environment variables:
1125
+
1126
+ ```javascript
1127
+ require('dotenv').config();
1128
+
1129
+ const okta = require('@okta/okta-sdk-nodejs');
1130
+
1131
+ const client = new okta.Client({
1132
+ orgUrl: process.env.OKTA_ORG_URL,
1133
+ token: process.env.OKTA_API_TOKEN
1134
+ });
1135
+ ```
1136
+
1137
+ ## OAuth 2.0 Private Key Configuration
1138
+
1139
+ For OAuth 2.0 authentication, use environment variables:
1140
+
1141
+ ```bash
1142
+ OKTA_ORG_URL=https://dev-1234567.okta.com
1143
+ OKTA_CLIENT_ID=your_client_id
1144
+ OKTA_PRIVATE_KEY='{"kty":"RSA","kid":"key-id","n":"...","e":"AQAB","d":"..."}'
1145
+ OKTA_KEY_ID=key-id
1146
+ OKTA_SCOPES=okta.users.manage,okta.groups.manage,okta.apps.manage
1147
+ ```
1148
+
1149
+ ```javascript
1150
+ require('dotenv').config();
1151
+ const okta = require('@okta/okta-sdk-nodejs');
1152
+
1153
+ const client = new okta.Client({
1154
+ orgUrl: process.env.OKTA_ORG_URL,
1155
+ authorizationMode: 'PrivateKey',
1156
+ clientId: process.env.OKTA_CLIENT_ID,
1157
+ scopes: process.env.OKTA_SCOPES.split(','),
1158
+ privateKey: process.env.OKTA_PRIVATE_KEY,
1159
+ keyId: process.env.OKTA_KEY_ID
1160
+ });
1161
+ ```
1162
+
1163
+ ## Useful Links
1164
+
1165
+ - Official Documentation: https://developer.okta.com/
1166
+ - API Reference: https://developer.okta.com/docs/reference/
1167
+ - Users API: https://developer.okta.com/docs/reference/api/users/
1168
+ - Groups API: https://developer.okta.com/docs/reference/api/groups/
1169
+ - Applications API: https://developer.okta.com/docs/reference/api/apps/
1170
+ - GitHub Repository: https://github.com/okta/okta-sdk-nodejs
1171
+ - NPM Package: https://www.npmjs.com/package/@okta/okta-sdk-nodejs