@agility/management-sdk 0.1.36 → 0.1.38

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 (263) hide show
  1. package/README.md +396 -317
  2. package/dist/apiMethods/clientInstance.d.ts +2 -0
  3. package/dist/apiMethods/clientInstance.js +11 -2
  4. package/dist/apiMethods/containerMethods.d.ts +3 -0
  5. package/dist/apiMethods/containerMethods.js +43 -9
  6. package/dist/apiMethods/contentMethods.d.ts +12 -0
  7. package/dist/apiMethods/contentMethods.js +100 -46
  8. package/dist/apiMethods/instanceMethods.d.ts +13 -0
  9. package/dist/apiMethods/instanceMethods.js +48 -0
  10. package/dist/apiMethods/pageMethods.d.ts +12 -0
  11. package/dist/apiMethods/pageMethods.js +88 -34
  12. package/dist/enums/contentViewType.d.ts +6 -0
  13. package/dist/enums/contentViewType.js +10 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.js +3 -0
  16. package/dist/models/fetchApiStatus.d.ts +38 -0
  17. package/dist/models/fetchApiStatus.js +2 -0
  18. package/dist/models/pagedResult.d.ts +4 -0
  19. package/dist/models/pagedResult.js +2 -0
  20. package/docs/asset-methods.md +381 -381
  21. package/docs/auth-component.md +360 -360
  22. package/docs/auth.md +593 -593
  23. package/docs/batch-methods.md +243 -243
  24. package/docs/cicd.md +606 -606
  25. package/docs/container-methods.md +267 -267
  26. package/docs/content-methods.md +491 -422
  27. package/docs/instance-methods.md +185 -105
  28. package/docs/instance-user-methods.md +230 -230
  29. package/docs/model-methods.md +433 -433
  30. package/docs/multi-instance-operations.md +191 -191
  31. package/docs/page-methods.md +737 -670
  32. package/docs/server-user-methods.md +279 -279
  33. package/docs/webhook-methods.md +451 -451
  34. package/license.txt +20 -20
  35. package/package.json +40 -40
  36. package/tsconfig.json +14 -14
  37. package/.cursor/api-coverage.md +0 -217
  38. package/.cursor/api-documentation-manifest.md +0 -275
  39. package/.cursor/api-functions-analysis.md +0 -111
  40. package/.cursor/breakout-manifest.md +0 -278
  41. package/.cursor/docs-final-check.md +0 -269
  42. package/.cursor/github-actions-improvements.md +0 -76
  43. package/.cursor/hardening.md +0 -271
  44. package/.cursor/linting-fix.md +0 -160
  45. package/.cursor/manifest.md +0 -243
  46. package/.cursor/mocks.md +0 -100
  47. package/.cursor/test-coverage.md +0 -841
  48. package/.env +0 -92
  49. package/coverage/base.css +0 -224
  50. package/coverage/block-navigation.js +0 -87
  51. package/coverage/coverage-summary.json +0 -43
  52. package/coverage/favicon.png +0 -0
  53. package/coverage/index.html +0 -161
  54. package/coverage/lcov-report/base.css +0 -224
  55. package/coverage/lcov-report/block-navigation.js +0 -87
  56. package/coverage/lcov-report/favicon.png +0 -0
  57. package/coverage/lcov-report/index.html +0 -161
  58. package/coverage/lcov-report/prettify.css +0 -1
  59. package/coverage/lcov-report/prettify.js +0 -2
  60. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  61. package/coverage/lcov-report/sorter.js +0 -210
  62. package/coverage/lcov-report/src/apiClient.ts.html +0 -199
  63. package/coverage/lcov-report/src/apiMethods/assetMethods.ts.html +0 -682
  64. package/coverage/lcov-report/src/apiMethods/batchMethods.ts.html +0 -736
  65. package/coverage/lcov-report/src/apiMethods/clientInstance.ts.html +0 -403
  66. package/coverage/lcov-report/src/apiMethods/containerMethods.ts.html +0 -460
  67. package/coverage/lcov-report/src/apiMethods/contentMethods.ts.html +0 -1183
  68. package/coverage/lcov-report/src/apiMethods/index.html +0 -266
  69. package/coverage/lcov-report/src/apiMethods/instanceMethods.ts.html +0 -160
  70. package/coverage/lcov-report/src/apiMethods/instanceUserMethods.ts.html +0 -268
  71. package/coverage/lcov-report/src/apiMethods/modelMethods.ts.html +0 -352
  72. package/coverage/lcov-report/src/apiMethods/pageMethods.ts.html +0 -1276
  73. package/coverage/lcov-report/src/apiMethods/serverUserMethods.ts.html +0 -196
  74. package/coverage/lcov-report/src/apiMethods/webhookMethods.ts.html +0 -271
  75. package/coverage/lcov-report/src/enums/batchItemType.ts.html +0 -106
  76. package/coverage/lcov-report/src/enums/batchOperationType.ts.html +0 -142
  77. package/coverage/lcov-report/src/enums/batchState..ts.html +0 -106
  78. package/coverage/lcov-report/src/enums/index.html +0 -161
  79. package/coverage/lcov-report/src/enums/workflowOperationType.ts.html +0 -175
  80. package/coverage/lcov-report/src/index.html +0 -116
  81. package/coverage/lcov-report/src/models/assetContainer.ts.html +0 -106
  82. package/coverage/lcov-report/src/models/assetGalleries.ts.html +0 -103
  83. package/coverage/lcov-report/src/models/assetMediaGrouping.ts.html +0 -136
  84. package/coverage/lcov-report/src/models/assetMediaGroupingMetaData.ts.html +0 -97
  85. package/coverage/lcov-report/src/models/batch.ts.html +0 -178
  86. package/coverage/lcov-report/src/models/batchItem.ts.html +0 -127
  87. package/coverage/lcov-report/src/models/container.ts.html +0 -232
  88. package/coverage/lcov-report/src/models/contentDefinitionTypeID.ts.html +0 -142
  89. package/coverage/lcov-report/src/models/contentItem.ts.html +0 -202
  90. package/coverage/lcov-report/src/models/contentSectionDefaultModule.ts.html +0 -106
  91. package/coverage/lcov-report/src/models/contentSectionDefinition.ts.html +0 -196
  92. package/coverage/lcov-report/src/models/contentViewColumn.ts.html +0 -109
  93. package/coverage/lcov-report/src/models/exception.ts.html +0 -109
  94. package/coverage/lcov-report/src/models/index.html +0 -476
  95. package/coverage/lcov-report/src/models/instanceRole.ts.html +0 -106
  96. package/coverage/lcov-report/src/models/instanceUser.ts.html +0 -130
  97. package/coverage/lcov-report/src/models/locales.ts.html +0 -100
  98. package/coverage/lcov-report/src/models/media.ts.html +0 -178
  99. package/coverage/lcov-report/src/models/model.ts.html +0 -172
  100. package/coverage/lcov-report/src/models/notification.ts.html +0 -124
  101. package/coverage/lcov-report/src/models/options.ts.html +0 -109
  102. package/coverage/lcov-report/src/models/pageItem.ts.html +0 -268
  103. package/coverage/lcov-report/src/models/pageModel.ts.html +0 -130
  104. package/coverage/lcov-report/src/models/sharedModule.ts.html +0 -106
  105. package/coverage/lcov-report/src/models/sitemap.ts.html +0 -148
  106. package/coverage/lcov-report/src/models/websiteUser.ts.html +0 -157
  107. package/coverage/lcov.info +0 -1459
  108. package/coverage/prettify.css +0 -1
  109. package/coverage/prettify.js +0 -2
  110. package/coverage/sort-arrow-sprite.png +0 -0
  111. package/coverage/sorter.js +0 -210
  112. package/coverage/src/apiClient.ts.html +0 -199
  113. package/coverage/src/apiMethods/assetMethods.ts.html +0 -682
  114. package/coverage/src/apiMethods/batchMethods.ts.html +0 -736
  115. package/coverage/src/apiMethods/clientInstance.ts.html +0 -403
  116. package/coverage/src/apiMethods/containerMethods.ts.html +0 -460
  117. package/coverage/src/apiMethods/contentMethods.ts.html +0 -1183
  118. package/coverage/src/apiMethods/index.html +0 -266
  119. package/coverage/src/apiMethods/instanceMethods.ts.html +0 -160
  120. package/coverage/src/apiMethods/instanceUserMethods.ts.html +0 -268
  121. package/coverage/src/apiMethods/modelMethods.ts.html +0 -352
  122. package/coverage/src/apiMethods/pageMethods.ts.html +0 -1276
  123. package/coverage/src/apiMethods/serverUserMethods.ts.html +0 -196
  124. package/coverage/src/apiMethods/webhookMethods.ts.html +0 -271
  125. package/coverage/src/enums/batchItemType.ts.html +0 -106
  126. package/coverage/src/enums/batchOperationType.ts.html +0 -142
  127. package/coverage/src/enums/batchState..ts.html +0 -106
  128. package/coverage/src/enums/index.html +0 -161
  129. package/coverage/src/enums/workflowOperationType.ts.html +0 -175
  130. package/coverage/src/index.html +0 -116
  131. package/coverage/src/models/assetContainer.ts.html +0 -106
  132. package/coverage/src/models/assetGalleries.ts.html +0 -103
  133. package/coverage/src/models/assetMediaGrouping.ts.html +0 -136
  134. package/coverage/src/models/assetMediaGroupingMetaData.ts.html +0 -97
  135. package/coverage/src/models/batch.ts.html +0 -178
  136. package/coverage/src/models/batchItem.ts.html +0 -127
  137. package/coverage/src/models/container.ts.html +0 -232
  138. package/coverage/src/models/contentDefinitionTypeID.ts.html +0 -142
  139. package/coverage/src/models/contentItem.ts.html +0 -202
  140. package/coverage/src/models/contentSectionDefaultModule.ts.html +0 -106
  141. package/coverage/src/models/contentSectionDefinition.ts.html +0 -196
  142. package/coverage/src/models/contentViewColumn.ts.html +0 -109
  143. package/coverage/src/models/exception.ts.html +0 -109
  144. package/coverage/src/models/index.html +0 -476
  145. package/coverage/src/models/instanceRole.ts.html +0 -106
  146. package/coverage/src/models/instanceUser.ts.html +0 -130
  147. package/coverage/src/models/locales.ts.html +0 -100
  148. package/coverage/src/models/media.ts.html +0 -178
  149. package/coverage/src/models/model.ts.html +0 -172
  150. package/coverage/src/models/notification.ts.html +0 -124
  151. package/coverage/src/models/options.ts.html +0 -109
  152. package/coverage/src/models/pageItem.ts.html +0 -268
  153. package/coverage/src/models/pageModel.ts.html +0 -130
  154. package/coverage/src/models/sharedModule.ts.html +0 -106
  155. package/coverage/src/models/sitemap.ts.html +0 -148
  156. package/coverage/src/models/websiteUser.ts.html +0 -157
  157. package/dist/.tsbuildinfo +0 -1
  158. package/dist/apiClient.d.ts.map +0 -1
  159. package/dist/apiClient.js.map +0 -1
  160. package/dist/apiMethods/assetMethods.d.ts.map +0 -1
  161. package/dist/apiMethods/assetMethods.js.map +0 -1
  162. package/dist/apiMethods/batchMethods.d.ts.map +0 -1
  163. package/dist/apiMethods/batchMethods.js.map +0 -1
  164. package/dist/apiMethods/clientInstance.d.ts.map +0 -1
  165. package/dist/apiMethods/clientInstance.js.map +0 -1
  166. package/dist/apiMethods/containerMethods.d.ts.map +0 -1
  167. package/dist/apiMethods/containerMethods.js.map +0 -1
  168. package/dist/apiMethods/contentMethods.d.ts.map +0 -1
  169. package/dist/apiMethods/contentMethods.js.map +0 -1
  170. package/dist/apiMethods/instanceMethods.d.ts.map +0 -1
  171. package/dist/apiMethods/instanceMethods.js.map +0 -1
  172. package/dist/apiMethods/instanceUserMethods.d.ts.map +0 -1
  173. package/dist/apiMethods/instanceUserMethods.js.map +0 -1
  174. package/dist/apiMethods/modelMethods.d.ts.map +0 -1
  175. package/dist/apiMethods/modelMethods.js.map +0 -1
  176. package/dist/apiMethods/pageMethods.d.ts.map +0 -1
  177. package/dist/apiMethods/pageMethods.js.map +0 -1
  178. package/dist/apiMethods/serverUserMethods.d.ts.map +0 -1
  179. package/dist/apiMethods/serverUserMethods.js.map +0 -1
  180. package/dist/apiMethods/webhookMethods.d.ts.map +0 -1
  181. package/dist/apiMethods/webhookMethods.js.map +0 -1
  182. package/dist/enums/assetGroupingType.d.ts.map +0 -1
  183. package/dist/enums/assetGroupingType.js.map +0 -1
  184. package/dist/enums/batchItemType.d.ts.map +0 -1
  185. package/dist/enums/batchItemType.js.map +0 -1
  186. package/dist/enums/batchOperationType.d.ts.map +0 -1
  187. package/dist/enums/batchOperationType.js.map +0 -1
  188. package/dist/enums/batchState..d.ts.map +0 -1
  189. package/dist/enums/batchState..js.map +0 -1
  190. package/dist/enums/pageItemTemplateType.d.ts.map +0 -1
  191. package/dist/enums/pageItemTemplateType.js.map +0 -1
  192. package/dist/enums/workflowOperationType.d.ts.map +0 -1
  193. package/dist/enums/workflowOperationType.js.map +0 -1
  194. package/dist/index.d.ts.map +0 -1
  195. package/dist/index.js.map +0 -1
  196. package/dist/models/assetContainer.d.ts.map +0 -1
  197. package/dist/models/assetContainer.js.map +0 -1
  198. package/dist/models/assetGalleries.d.ts.map +0 -1
  199. package/dist/models/assetGalleries.js.map +0 -1
  200. package/dist/models/assetMediaGrouping.d.ts.map +0 -1
  201. package/dist/models/assetMediaGrouping.js.map +0 -1
  202. package/dist/models/assetMediaGroupingMetaData.d.ts.map +0 -1
  203. package/dist/models/assetMediaGroupingMetaData.js.map +0 -1
  204. package/dist/models/batch.d.ts.map +0 -1
  205. package/dist/models/batch.js.map +0 -1
  206. package/dist/models/batchItem.d.ts.map +0 -1
  207. package/dist/models/batchItem.js.map +0 -1
  208. package/dist/models/batchTypes.d.ts.map +0 -1
  209. package/dist/models/batchTypes.js.map +0 -1
  210. package/dist/models/container.d.ts.map +0 -1
  211. package/dist/models/container.js.map +0 -1
  212. package/dist/models/contentDefinitionTypeID.d.ts.map +0 -1
  213. package/dist/models/contentDefinitionTypeID.js.map +0 -1
  214. package/dist/models/contentItem.d.ts.map +0 -1
  215. package/dist/models/contentItem.js.map +0 -1
  216. package/dist/models/contentItemHistory.d.ts.map +0 -1
  217. package/dist/models/contentItemHistory.js.map +0 -1
  218. package/dist/models/contentListFilterModel.d.ts.map +0 -1
  219. package/dist/models/contentListFilterModel.js.map +0 -1
  220. package/dist/models/contentSectionDefaultModule.d.ts.map +0 -1
  221. package/dist/models/contentSectionDefaultModule.js.map +0 -1
  222. package/dist/models/contentSectionDefinition.d.ts.map +0 -1
  223. package/dist/models/contentSectionDefinition.js.map +0 -1
  224. package/dist/models/contentViewColumn.d.ts.map +0 -1
  225. package/dist/models/contentViewColumn.js.map +0 -1
  226. package/dist/models/exception.d.ts.map +0 -1
  227. package/dist/models/exception.js.map +0 -1
  228. package/dist/models/instanceRole.d.ts.map +0 -1
  229. package/dist/models/instanceRole.js.map +0 -1
  230. package/dist/models/instanceUser.d.ts.map +0 -1
  231. package/dist/models/instanceUser.js.map +0 -1
  232. package/dist/models/itemComments.d.ts.map +0 -1
  233. package/dist/models/itemComments.js.map +0 -1
  234. package/dist/models/listParams.d.ts.map +0 -1
  235. package/dist/models/listParams.js.map +0 -1
  236. package/dist/models/locales.d.ts.map +0 -1
  237. package/dist/models/locales.js.map +0 -1
  238. package/dist/models/media.d.ts.map +0 -1
  239. package/dist/models/media.js.map +0 -1
  240. package/dist/models/model.d.ts.map +0 -1
  241. package/dist/models/model.js.map +0 -1
  242. package/dist/models/notification.d.ts.map +0 -1
  243. package/dist/models/notification.js.map +0 -1
  244. package/dist/models/options.d.ts.map +0 -1
  245. package/dist/models/options.js.map +0 -1
  246. package/dist/models/pageHistory.d.ts.map +0 -1
  247. package/dist/models/pageHistory.js.map +0 -1
  248. package/dist/models/pageItem.d.ts.map +0 -1
  249. package/dist/models/pageItem.js.map +0 -1
  250. package/dist/models/pageModel.d.ts.map +0 -1
  251. package/dist/models/pageModel.js.map +0 -1
  252. package/dist/models/serverUser.d.ts.map +0 -1
  253. package/dist/models/serverUser.js.map +0 -1
  254. package/dist/models/sharedModule.d.ts.map +0 -1
  255. package/dist/models/sharedModule.js.map +0 -1
  256. package/dist/models/sitemap.d.ts.map +0 -1
  257. package/dist/models/sitemap.js.map +0 -1
  258. package/dist/models/webhook.d.ts.map +0 -1
  259. package/dist/models/webhook.js.map +0 -1
  260. package/dist/models/websiteListing.d.ts.map +0 -1
  261. package/dist/models/websiteListing.js.map +0 -1
  262. package/dist/models/websiteUser.d.ts.map +0 -1
  263. package/dist/models/websiteUser.js.map +0 -1
package/docs/auth.md CHANGED
@@ -1,594 +1,594 @@
1
- # Agility CMS & Management API TypeScript SDK
2
-
3
- ## Authentication & Setup
4
-
5
- This guide covers how to authenticate with the Agility CMS Management API and initialize the SDK for making API requests.
6
-
7
- **🚀 NEW: Simplified Authentication**
8
- We now provide a streamlined authentication experience with secure token storage and automatic token refresh. The new `ApiClient.auth()` method handles the entire OAuth flow internally.
9
-
10
- ### Prerequisites
11
- 1. Valid Agility CMS credentials
12
- 2. A configured OAuth application in your Agility CMS instance
13
- 3. A valid redirect URI for OAuth flow
14
- 4. **Node.js**: For secure token storage, keytar is required (`npm install keytar`)
15
-
16
- ### Setup Instructions
17
-
18
- #### Install keytar for Secure Token Storage
19
- ```bash
20
- npm install keytar
21
- ```
22
-
23
- **Platform Requirements:**
24
- - **macOS**: Uses Keychain (built-in)
25
- - **Windows**: Uses Windows Credential Store (built-in)
26
- - **Linux**: Requires `libsecret` development package
27
- ```bash
28
- # Ubuntu/Debian
29
- sudo apt-get install libsecret-1-dev
30
-
31
- # Red Hat/CentOS
32
- sudo yum install libsecret-devel
33
- ```
34
-
35
- ### Authentication Approaches
36
-
37
- You have two options for authentication:
38
-
39
- #### 1. **Recommended: Simple OAuth Flow**
40
- Use the new `ApiClient.auth()` method for streamlined authentication:
41
-
42
- ```typescript
43
- import * as mgmtApi from '@agility/management-sdk';
44
-
45
- // Simple OAuth authentication
46
- const apiClient = new mgmtApi.ApiClient();
47
- await apiClient.auth();
48
-
49
- // Client is now authenticated - make API calls directly
50
- const guid = "your-website-guid";
51
- const locale = "en-us";
52
- const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
53
- ```
54
-
55
- The `auth()` method:
56
- - Generates OAuth authorization URL
57
- - Handles token exchange automatically
58
- - Stores tokens securely using keytar
59
- - Provides automatic token refresh
60
-
61
- #### 2. **Manual Token Management (Existing Pattern)**
62
- For applications that need to handle tokens manually, the traditional approach is still fully supported:
63
-
64
- ```typescript
65
- import * as mgmtApi from "@agility/management-sdk";
66
-
67
- // Manual token approach (still supported)
68
- const options = new mgmtApi.Options();
69
- options.token = "your-access-token";
70
- const apiClient = new mgmtApi.ApiClient(options);
71
-
72
- const guid = "your-website-guid";
73
- const locale = "en-us";
74
-
75
- const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
76
- console.log(JSON.stringify(contentItem));
77
- ```
78
-
79
- For custom OAuth implementations, you can handle the OAuth flow manually:
80
-
81
- Before using the SDK, you must authenticate against the Agility Management API to obtain a valid access token. This token is required for all subsequent API requests.
82
-
83
- The authentication process uses OAuth 2.0 and requires multiple steps:
84
-
85
- #### Step 1: Initiate Authorization Flow
86
-
87
- First, initiate the authorization flow by making a GET request to the authorization endpoint:
88
-
89
- ```javascript
90
- const authUrl = 'https://mgmt.aglty.io/oauth/authorize';
91
-
92
- //if you wish to implement offline access using refresh tokens, use this URL (enables refresh tokens)
93
- //const authUrl = 'https://mgmt.aglty.io/oauth/authorize?scope=offline-access ';
94
-
95
- const params = new URLSearchParams({
96
- response_type: 'code',
97
- redirect_uri: 'YOUR_REDIRECT_URI',
98
- state: 'YOUR_STATE',
99
- scope: 'openid profile email offline_access'
100
- });
101
-
102
- // Redirect the user to the authorization URL
103
- window.location.href = `${authUrl}?${params.toString()}`;
104
- ```
105
-
106
- #### Step 2: Exchange Authorization Code for Access Token
107
-
108
- After successful authentication, you'll receive an authorization code at your redirect URI. Use this code to obtain an access token:
109
-
110
- ```javascript
111
- const response = await fetch('https://mgmt.aglty.io/oauth/token', {
112
- method: 'POST',
113
- headers: {
114
- 'Content-Type': 'application/x-www-form-urlencoded'
115
- },
116
- body: new URLSearchParams({
117
- code: 'YOUR_AUTHORIZATION_CODE'
118
- })
119
- });
120
-
121
- const { access_token, refresh_token, expires_in } = await response.json();
122
- ```
123
-
124
- #### Step 3: Initialize the SDK
125
-
126
- Use the obtained token to initialize the SDK:
127
-
128
- ```javascript
129
- import * as mgmtApi from "@agility/management-sdk";
130
-
131
- // Initialize the Options Class with your authentication token
132
- let options = new mgmtApi.Options();
133
- options.token = access_token; // Use the token obtained from authentication
134
-
135
- // Initialize the APIClient Class
136
- let apiClient = new mgmtApi.ApiClient(options);
137
-
138
- let guid = "<<Provide the Guid of the Website>>";
139
- let locale = "<<Provide the locale of the Website>>"; // Example: en-us
140
-
141
- // Now you can make authenticated requests
142
- var contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
143
- console.log(JSON.stringify(contentItem));
144
- ```
145
-
146
- #### Step 4: Refresh Access Tokens
147
-
148
- When the access token expires, use the refresh token to obtain a new access token:
149
-
150
- ```javascript
151
- const response = await fetch('https://mgmt.aglty.io/oauth/refresh', {
152
- method: 'POST',
153
- headers: {
154
- 'Content-Type': 'application/json'
155
- },
156
- body: JSON.stringify({
157
- refresh_token: 'YOUR_REFRESH_TOKEN'
158
- })
159
- });
160
-
161
- const { access_token, refresh_token, expires_in } = await response.json();
162
- ```
163
-
164
- ### Important Authentication Notes
165
-
166
- - **Token Lifetime**: The access token has a limited lifetime (typically 1 hour)
167
- - **Refresh Tokens**: The refresh token can be used to obtain new access tokens
168
- - **Security**: Store refresh tokens securely and never expose them in client-side code
169
- - **Error Handling**: Implement proper error handling for authentication failures
170
-
171
- ### Making API Requests
172
-
173
- Once authenticated, you can make requests using the SDK:
174
-
175
- #### Using New Simple Authentication (Recommended)
176
- ```typescript
177
- import * as mgmtApi from '@agility/management-sdk';
178
-
179
- // Simple OAuth authentication
180
- const apiClient = new mgmtApi.ApiClient();
181
- await apiClient.auth();
182
-
183
- // Client is now authenticated and handles token refresh automatically
184
- const guid = "your-website-guid";
185
- const locale = "en-us";
186
- const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
187
- console.log(JSON.stringify(contentItem));
188
- ```
189
-
190
- #### Manual Client Creation (Existing Pattern)
191
- ```javascript
192
- import * as mgmtApi from "@agility/management-sdk";
193
-
194
- //initialize the Options Class
195
- let options = new mgmtApi.Options();
196
-
197
- options.token = "<<Provide Auth Token>>"
198
- //Initialize the APIClient Class
199
- let apiClient = new mgmtApi.ApiClient(options);
200
-
201
- let guid = "<<Provide the Guid of the Website>>";
202
- let locale = "<<Provide the locale of the Website>>"; //Example: en-us
203
-
204
- //make the request: get a content item with the ID '22'
205
- var contentItem = await apiClient.contentMethods.getContentItem(22,guid, locale);
206
-
207
- //To log the response of the contentItem object in console.
208
- console.log(JSON.stringify(contentItem));
209
- ```
210
-
211
- ### OAuth Flow Examples
212
-
213
- #### For Web Applications
214
-
215
- ```javascript
216
- // Redirect user to authorization URL
217
- function initiateAuth() {
218
- const authUrl = 'https://mgmt.aglty.io/oauth/authorize';
219
- const params = new URLSearchParams({
220
- response_type: 'code',
221
- redirect_uri: window.location.origin + '/auth/callback',
222
- state: generateRandomState(),
223
- scope: 'openid profile email offline_access'
224
- });
225
-
226
- window.location.href = `${authUrl}?${params.toString()}`;
227
- }
228
-
229
- // Handle callback in your redirect URI endpoint
230
- async function handleAuthCallback(code) {
231
- try {
232
- const response = await fetch('https://mgmt.aglty.io/oauth/token', {
233
- method: 'POST',
234
- headers: {
235
- 'Content-Type': 'application/x-www-form-urlencoded'
236
- },
237
- body: new URLSearchParams({
238
- code: code
239
- })
240
- });
241
-
242
- const tokens = await response.json();
243
-
244
- // Store tokens securely
245
- localStorage.setItem('access_token', tokens.access_token);
246
- localStorage.setItem('refresh_token', tokens.refresh_token);
247
-
248
- return tokens;
249
- } catch (error) {
250
- console.error('Authentication failed:', error);
251
- throw error;
252
- }
253
- }
254
- ```
255
-
256
- #### For Server-Side Applications
257
-
258
- ```javascript
259
- // Express.js example
260
- app.get('/auth/agility', (req, res) => {
261
- const authUrl = 'https://mgmt.aglty.io/oauth/authorize';
262
- const params = new URLSearchParams({
263
- response_type: 'code',
264
- redirect_uri: 'https://yourapp.com/auth/callback',
265
- state: req.session.state,
266
- scope: 'openid profile email offline_access'
267
- });
268
-
269
- res.redirect(`${authUrl}?${params.toString()}`);
270
- });
271
-
272
- app.get('/auth/callback', async (req, res) => {
273
- const { code, state } = req.query;
274
-
275
- // Verify state parameter
276
- if (state !== req.session.state) {
277
- return res.status(400).send('Invalid state parameter');
278
- }
279
-
280
- try {
281
- const response = await fetch('https://mgmt.aglty.io/oauth/token', {
282
- method: 'POST',
283
- headers: {
284
- 'Content-Type': 'application/x-www-form-urlencoded'
285
- },
286
- body: new URLSearchParams({
287
- code: code
288
- })
289
- });
290
-
291
- const tokens = await response.json();
292
-
293
- // Store tokens in session or database
294
- req.session.tokens = tokens;
295
-
296
- res.redirect('/dashboard');
297
- } catch (error) {
298
- res.status(500).send('Authentication failed');
299
- }
300
- });
301
- ```
302
-
303
- ### Token Management
304
-
305
- #### Automatic Token Refresh
306
-
307
- ```javascript
308
- class AgilityTokenManager {
309
- constructor(refreshToken) {
310
- this.refreshToken = refreshToken;
311
- this.accessToken = null;
312
- this.expiresAt = null;
313
- }
314
-
315
- async getValidToken() {
316
- if (!this.accessToken || Date.now() >= this.expiresAt) {
317
- await this.refreshAccessToken();
318
- }
319
- return this.accessToken;
320
- }
321
-
322
- async refreshAccessToken() {
323
- try {
324
- const response = await fetch('https://mgmt.aglty.io/oauth/refresh', {
325
- method: 'POST',
326
- headers: {
327
- 'Content-Type': 'application/json'
328
- },
329
- body: JSON.stringify({
330
- refresh_token: this.refreshToken
331
- })
332
- });
333
-
334
- const tokens = await response.json();
335
-
336
- this.accessToken = tokens.access_token;
337
- this.refreshToken = tokens.refresh_token; // Update refresh token if provided
338
- this.expiresAt = Date.now() + (tokens.expires_in * 1000);
339
-
340
- return tokens;
341
- } catch (error) {
342
- console.error('Token refresh failed:', error);
343
- throw error;
344
- }
345
- }
346
- }
347
-
348
- // Usage
349
- const tokenManager = new AgilityTokenManager('your-refresh-token');
350
- const token = await tokenManager.getValidToken();
351
-
352
- const options = new mgmtApi.Options();
353
- options.token = token;
354
- const apiClient = new mgmtApi.ApiClient(options);
355
- ```
356
-
357
- ### Error Handling
358
-
359
- #### Common Authentication Errors
360
-
361
- ```javascript
362
- async function makeAuthenticatedRequest() {
363
- try {
364
- const apiClient = new mgmtApi.ApiClient({ token: accessToken });
365
- const result = await apiClient.contentMethods.getContentItem(123, guid, locale);
366
- return result;
367
- } catch (error) {
368
- if (error.response?.status === 401) {
369
- // Token expired or invalid
370
- console.log('Authentication failed - refreshing token');
371
- await refreshAccessToken();
372
-
373
- // Retry the request
374
- const apiClient = new mgmtApi.ApiClient({ token: newAccessToken });
375
- return await apiClient.contentMethods.getContentItem(123, guid, locale);
376
- } else if (error.response?.status === 403) {
377
- // Insufficient permissions
378
- console.error('Access denied - insufficient permissions');
379
- throw new Error('User does not have permission for this operation');
380
- } else {
381
- // Other errors
382
- console.error('API request failed:', error.message);
383
- throw error;
384
- }
385
- }
386
- }
387
- ```
388
-
389
- ### Migration Guide
390
-
391
- #### Migrating from Manual OAuth to Simple Authentication
392
-
393
- **Before (Manual OAuth):**
394
- ```typescript
395
- // Old approach - manual OAuth handling
396
- import * as mgmtApi from '@agility/management-sdk';
397
-
398
- const options = new mgmtApi.Options();
399
- options.token = 'manually-obtained-token';
400
- const apiClient = new mgmtApi.ApiClient(options);
401
-
402
- // Manual token refresh required
403
- const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
404
- ```
405
-
406
- **After (Simple Authentication):**
407
- ```typescript
408
- // New approach - automatic OAuth handling
409
- import * as mgmtApi from '@agility/management-sdk';
410
-
411
- const apiClient = new mgmtApi.ApiClient();
412
- await apiClient.auth();
413
-
414
- // Automatic token refresh handled internally
415
- const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
416
- ```
417
-
418
- #### Migrating from AuthMethods Class
419
-
420
- **Before (AuthMethods Class):**
421
- ```typescript
422
- import { AuthMethods } from '@agility/management-sdk';
423
-
424
- const auth = new AuthMethods();
425
- const client = auth.createAuthenticatedClient('token');
426
- ```
427
-
428
- **After (Simple Authentication):**
429
- ```typescript
430
- import * as mgmtApi from '@agility/management-sdk';
431
-
432
- const apiClient = new mgmtApi.ApiClient();
433
- await apiClient.auth();
434
- ```
435
-
436
- ### Advanced Features
437
-
438
- #### Secure Token Storage
439
- The new authentication system uses OS-level secure storage:
440
-
441
- - **macOS**: Keychain Access
442
- - **Windows**: Windows Credential Store
443
- - **Linux**: libsecret (GNOME Keyring)
444
-
445
- Tokens are encrypted and stored securely, with automatic cleanup on logout.
446
-
447
- #### Automatic Token Refresh
448
- The SDK now handles token refresh automatically:
449
-
450
- ```typescript
451
- const apiClient = new mgmtApi.ApiClient();
452
- await apiClient.auth();
453
-
454
- // Token refresh happens automatically on 401 errors
455
- const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
456
- // If token was expired, it gets refreshed transparently
457
- ```
458
-
459
- #### Custom OAuth Configuration
460
- You can customize the OAuth flow:
461
-
462
- ```typescript
463
- const apiClient = new mgmtApi.ApiClient();
464
- await apiClient.auth({
465
- redirectUri: 'https://yourapp.com/custom-callback',
466
- scope: 'openid profile email offline_access',
467
- region: 'us' // or 'ca', 'eu', 'au', 'dev'
468
- });
469
- ```
470
-
471
- #### Manual Token Exchange
472
- For custom OAuth implementations:
473
-
474
- ```typescript
475
- const apiClient = new mgmtApi.ApiClient();
476
-
477
- // Exchange authorization code for tokens
478
- const tokens = await apiClient.exchangeCodeForToken({
479
- code: 'authorization_code_from_callback',
480
- redirectUri: 'https://yourapp.com/auth/callback'
481
- });
482
-
483
- // Tokens are automatically stored and used
484
- ```
485
-
486
- ### Best Practices
487
-
488
- #### Security Considerations
489
-
490
- 1. **Use secure token storage (automatic with new auth)**
491
- ```typescript
492
- // ✅ Recommended - automatic secure storage
493
- const apiClient = new mgmtApi.ApiClient();
494
- await apiClient.auth(); // Tokens stored securely in OS keychain
495
-
496
- // ✅ CI/CD - manual token (for automated environments)
497
- const options = new mgmtApi.Options();
498
- options.token = process.env.AGILITY_ACCESS_TOKEN;
499
- const apiClient = new mgmtApi.ApiClient(options);
500
-
501
- // ❌ Bad - hardcoded tokens
502
- options.token = 'your-secret-token'; // Never do this
503
- ```
504
-
505
- 2. **Leverage automatic token refresh**
506
- ```typescript
507
- // ✅ Automatic token refresh (new approach)
508
- const apiClient = new mgmtApi.ApiClient();
509
- await apiClient.auth();
510
-
511
- // Token refresh happens automatically on 401 errors
512
- const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
513
- ```
514
-
515
- 3. **Handle authentication errors gracefully**
516
- ```typescript
517
- const apiClient = new mgmtApi.ApiClient();
518
-
519
- try {
520
- await apiClient.auth();
521
- const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
522
- } catch (error) {
523
- if (error.message.includes('OAuth flow requires manual implementation')) {
524
- // Handle OAuth flow manually
525
- console.log('Visit the OAuth URL to authenticate');
526
- } else {
527
- // Handle other auth errors
528
- console.error('Authentication failed:', error);
529
- }
530
- }
531
- ```
532
-
533
- 4. **Clear tokens on logout**
534
- ```typescript
535
- const apiClient = new mgmtApi.ApiClient();
536
- await apiClient.auth();
537
-
538
- // ... use API client ...
539
-
540
- // Clear tokens securely on logout
541
- await apiClient.clearToken();
542
- ```
543
-
544
- #### Performance Optimization
545
-
546
- 1. **Reuse API client instances**
547
- ```javascript
548
- // ✅ Good - single instance
549
- const apiClient = new mgmtApi.ApiClient(options);
550
-
551
- // Use the same instance for multiple requests
552
- const content1 = await apiClient.contentMethods.getContentItem(1, guid, locale);
553
- const content2 = await apiClient.contentMethods.getContentItem(2, guid, locale);
554
- ```
555
-
556
- 2. **Implement request caching**
557
- ```javascript
558
- class CachedAgilityClient {
559
- constructor(options) {
560
- this.client = new mgmtApi.ApiClient(options);
561
- this.cache = new Map();
562
- }
563
-
564
- async getContentItem(id, guid, locale) {
565
- const cacheKey = `content-${id}-${guid}-${locale}`;
566
-
567
- if (this.cache.has(cacheKey)) {
568
- return this.cache.get(cacheKey);
569
- }
570
-
571
- const result = await this.client.contentMethods.getContentItem(id, guid, locale);
572
- this.cache.set(cacheKey, result);
573
-
574
- return result;
575
- }
576
- }
577
- ```
578
-
579
- ---
580
-
581
- ## Navigation
582
- - [← Back to Main Documentation](../README.md)
583
- - [CI/CD & Automated Environments](./cicd.md)
584
- - [AssetMethods](./asset-methods.md)
585
- - [BatchMethods](./batch-methods.md)
586
- - [ContentMethods](./content-methods.md)
587
- - [ContainerMethods](./container-methods.md)
588
- - [InstanceMethods](./instance-methods.md)
589
- - [InstanceUserMethods](./instance-user-methods.md)
590
- - [ModelMethods](./model-methods.md)
591
- - [PageMethods](./page-methods.md)
592
- - [ServerUserMethods](./server-user-methods.md)
593
- - [WebhookMethods](./webhook-methods.md)
1
+ # Agility CMS & Management API TypeScript SDK
2
+
3
+ ## Authentication & Setup
4
+
5
+ This guide covers how to authenticate with the Agility CMS Management API and initialize the SDK for making API requests.
6
+
7
+ **🚀 NEW: Simplified Authentication**
8
+ We now provide a streamlined authentication experience with secure token storage and automatic token refresh. The new `ApiClient.auth()` method handles the entire OAuth flow internally.
9
+
10
+ ### Prerequisites
11
+ 1. Valid Agility CMS credentials
12
+ 2. A configured OAuth application in your Agility CMS instance
13
+ 3. A valid redirect URI for OAuth flow
14
+ 4. **Node.js**: For secure token storage, keytar is required (`npm install keytar`)
15
+
16
+ ### Setup Instructions
17
+
18
+ #### Install keytar for Secure Token Storage
19
+ ```bash
20
+ npm install keytar
21
+ ```
22
+
23
+ **Platform Requirements:**
24
+ - **macOS**: Uses Keychain (built-in)
25
+ - **Windows**: Uses Windows Credential Store (built-in)
26
+ - **Linux**: Requires `libsecret` development package
27
+ ```bash
28
+ # Ubuntu/Debian
29
+ sudo apt-get install libsecret-1-dev
30
+
31
+ # Red Hat/CentOS
32
+ sudo yum install libsecret-devel
33
+ ```
34
+
35
+ ### Authentication Approaches
36
+
37
+ You have two options for authentication:
38
+
39
+ #### 1. **Recommended: Simple OAuth Flow**
40
+ Use the new `ApiClient.auth()` method for streamlined authentication:
41
+
42
+ ```typescript
43
+ import * as mgmtApi from '@agility/management-sdk';
44
+
45
+ // Simple OAuth authentication
46
+ const apiClient = new mgmtApi.ApiClient();
47
+ await apiClient.auth();
48
+
49
+ // Client is now authenticated - make API calls directly
50
+ const guid = "your-website-guid";
51
+ const locale = "en-us";
52
+ const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
53
+ ```
54
+
55
+ The `auth()` method:
56
+ - Generates OAuth authorization URL
57
+ - Handles token exchange automatically
58
+ - Stores tokens securely using keytar
59
+ - Provides automatic token refresh
60
+
61
+ #### 2. **Manual Token Management (Existing Pattern)**
62
+ For applications that need to handle tokens manually, the traditional approach is still fully supported:
63
+
64
+ ```typescript
65
+ import * as mgmtApi from "@agility/management-sdk";
66
+
67
+ // Manual token approach (still supported)
68
+ const options = new mgmtApi.Options();
69
+ options.token = "your-access-token";
70
+ const apiClient = new mgmtApi.ApiClient(options);
71
+
72
+ const guid = "your-website-guid";
73
+ const locale = "en-us";
74
+
75
+ const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
76
+ console.log(JSON.stringify(contentItem));
77
+ ```
78
+
79
+ For custom OAuth implementations, you can handle the OAuth flow manually:
80
+
81
+ Before using the SDK, you must authenticate against the Agility Management API to obtain a valid access token. This token is required for all subsequent API requests.
82
+
83
+ The authentication process uses OAuth 2.0 and requires multiple steps:
84
+
85
+ #### Step 1: Initiate Authorization Flow
86
+
87
+ First, initiate the authorization flow by making a GET request to the authorization endpoint:
88
+
89
+ ```javascript
90
+ const authUrl = 'https://mgmt.aglty.io/oauth/authorize';
91
+
92
+ //if you wish to implement offline access using refresh tokens, use this URL (enables refresh tokens)
93
+ //const authUrl = 'https://mgmt.aglty.io/oauth/authorize?scope=offline-access ';
94
+
95
+ const params = new URLSearchParams({
96
+ response_type: 'code',
97
+ redirect_uri: 'YOUR_REDIRECT_URI',
98
+ state: 'YOUR_STATE',
99
+ scope: 'openid profile email offline_access'
100
+ });
101
+
102
+ // Redirect the user to the authorization URL
103
+ window.location.href = `${authUrl}?${params.toString()}`;
104
+ ```
105
+
106
+ #### Step 2: Exchange Authorization Code for Access Token
107
+
108
+ After successful authentication, you'll receive an authorization code at your redirect URI. Use this code to obtain an access token:
109
+
110
+ ```javascript
111
+ const response = await fetch('https://mgmt.aglty.io/oauth/token', {
112
+ method: 'POST',
113
+ headers: {
114
+ 'Content-Type': 'application/x-www-form-urlencoded'
115
+ },
116
+ body: new URLSearchParams({
117
+ code: 'YOUR_AUTHORIZATION_CODE'
118
+ })
119
+ });
120
+
121
+ const { access_token, refresh_token, expires_in } = await response.json();
122
+ ```
123
+
124
+ #### Step 3: Initialize the SDK
125
+
126
+ Use the obtained token to initialize the SDK:
127
+
128
+ ```javascript
129
+ import * as mgmtApi from "@agility/management-sdk";
130
+
131
+ // Initialize the Options Class with your authentication token
132
+ let options = new mgmtApi.Options();
133
+ options.token = access_token; // Use the token obtained from authentication
134
+
135
+ // Initialize the APIClient Class
136
+ let apiClient = new mgmtApi.ApiClient(options);
137
+
138
+ let guid = "<<Provide the Guid of the Website>>";
139
+ let locale = "<<Provide the locale of the Website>>"; // Example: en-us
140
+
141
+ // Now you can make authenticated requests
142
+ var contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
143
+ console.log(JSON.stringify(contentItem));
144
+ ```
145
+
146
+ #### Step 4: Refresh Access Tokens
147
+
148
+ When the access token expires, use the refresh token to obtain a new access token:
149
+
150
+ ```javascript
151
+ const response = await fetch('https://mgmt.aglty.io/oauth/refresh', {
152
+ method: 'POST',
153
+ headers: {
154
+ 'Content-Type': 'application/json'
155
+ },
156
+ body: JSON.stringify({
157
+ refresh_token: 'YOUR_REFRESH_TOKEN'
158
+ })
159
+ });
160
+
161
+ const { access_token, refresh_token, expires_in } = await response.json();
162
+ ```
163
+
164
+ ### Important Authentication Notes
165
+
166
+ - **Token Lifetime**: The access token has a limited lifetime (typically 1 hour)
167
+ - **Refresh Tokens**: The refresh token can be used to obtain new access tokens
168
+ - **Security**: Store refresh tokens securely and never expose them in client-side code
169
+ - **Error Handling**: Implement proper error handling for authentication failures
170
+
171
+ ### Making API Requests
172
+
173
+ Once authenticated, you can make requests using the SDK:
174
+
175
+ #### Using New Simple Authentication (Recommended)
176
+ ```typescript
177
+ import * as mgmtApi from '@agility/management-sdk';
178
+
179
+ // Simple OAuth authentication
180
+ const apiClient = new mgmtApi.ApiClient();
181
+ await apiClient.auth();
182
+
183
+ // Client is now authenticated and handles token refresh automatically
184
+ const guid = "your-website-guid";
185
+ const locale = "en-us";
186
+ const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
187
+ console.log(JSON.stringify(contentItem));
188
+ ```
189
+
190
+ #### Manual Client Creation (Existing Pattern)
191
+ ```javascript
192
+ import * as mgmtApi from "@agility/management-sdk";
193
+
194
+ //initialize the Options Class
195
+ let options = new mgmtApi.Options();
196
+
197
+ options.token = "<<Provide Auth Token>>"
198
+ //Initialize the APIClient Class
199
+ let apiClient = new mgmtApi.ApiClient(options);
200
+
201
+ let guid = "<<Provide the Guid of the Website>>";
202
+ let locale = "<<Provide the locale of the Website>>"; //Example: en-us
203
+
204
+ //make the request: get a content item with the ID '22'
205
+ var contentItem = await apiClient.contentMethods.getContentItem(22,guid, locale);
206
+
207
+ //To log the response of the contentItem object in console.
208
+ console.log(JSON.stringify(contentItem));
209
+ ```
210
+
211
+ ### OAuth Flow Examples
212
+
213
+ #### For Web Applications
214
+
215
+ ```javascript
216
+ // Redirect user to authorization URL
217
+ function initiateAuth() {
218
+ const authUrl = 'https://mgmt.aglty.io/oauth/authorize';
219
+ const params = new URLSearchParams({
220
+ response_type: 'code',
221
+ redirect_uri: window.location.origin + '/auth/callback',
222
+ state: generateRandomState(),
223
+ scope: 'openid profile email offline_access'
224
+ });
225
+
226
+ window.location.href = `${authUrl}?${params.toString()}`;
227
+ }
228
+
229
+ // Handle callback in your redirect URI endpoint
230
+ async function handleAuthCallback(code) {
231
+ try {
232
+ const response = await fetch('https://mgmt.aglty.io/oauth/token', {
233
+ method: 'POST',
234
+ headers: {
235
+ 'Content-Type': 'application/x-www-form-urlencoded'
236
+ },
237
+ body: new URLSearchParams({
238
+ code: code
239
+ })
240
+ });
241
+
242
+ const tokens = await response.json();
243
+
244
+ // Store tokens securely
245
+ localStorage.setItem('access_token', tokens.access_token);
246
+ localStorage.setItem('refresh_token', tokens.refresh_token);
247
+
248
+ return tokens;
249
+ } catch (error) {
250
+ console.error('Authentication failed:', error);
251
+ throw error;
252
+ }
253
+ }
254
+ ```
255
+
256
+ #### For Server-Side Applications
257
+
258
+ ```javascript
259
+ // Express.js example
260
+ app.get('/auth/agility', (req, res) => {
261
+ const authUrl = 'https://mgmt.aglty.io/oauth/authorize';
262
+ const params = new URLSearchParams({
263
+ response_type: 'code',
264
+ redirect_uri: 'https://yourapp.com/auth/callback',
265
+ state: req.session.state,
266
+ scope: 'openid profile email offline_access'
267
+ });
268
+
269
+ res.redirect(`${authUrl}?${params.toString()}`);
270
+ });
271
+
272
+ app.get('/auth/callback', async (req, res) => {
273
+ const { code, state } = req.query;
274
+
275
+ // Verify state parameter
276
+ if (state !== req.session.state) {
277
+ return res.status(400).send('Invalid state parameter');
278
+ }
279
+
280
+ try {
281
+ const response = await fetch('https://mgmt.aglty.io/oauth/token', {
282
+ method: 'POST',
283
+ headers: {
284
+ 'Content-Type': 'application/x-www-form-urlencoded'
285
+ },
286
+ body: new URLSearchParams({
287
+ code: code
288
+ })
289
+ });
290
+
291
+ const tokens = await response.json();
292
+
293
+ // Store tokens in session or database
294
+ req.session.tokens = tokens;
295
+
296
+ res.redirect('/dashboard');
297
+ } catch (error) {
298
+ res.status(500).send('Authentication failed');
299
+ }
300
+ });
301
+ ```
302
+
303
+ ### Token Management
304
+
305
+ #### Automatic Token Refresh
306
+
307
+ ```javascript
308
+ class AgilityTokenManager {
309
+ constructor(refreshToken) {
310
+ this.refreshToken = refreshToken;
311
+ this.accessToken = null;
312
+ this.expiresAt = null;
313
+ }
314
+
315
+ async getValidToken() {
316
+ if (!this.accessToken || Date.now() >= this.expiresAt) {
317
+ await this.refreshAccessToken();
318
+ }
319
+ return this.accessToken;
320
+ }
321
+
322
+ async refreshAccessToken() {
323
+ try {
324
+ const response = await fetch('https://mgmt.aglty.io/oauth/refresh', {
325
+ method: 'POST',
326
+ headers: {
327
+ 'Content-Type': 'application/json'
328
+ },
329
+ body: JSON.stringify({
330
+ refresh_token: this.refreshToken
331
+ })
332
+ });
333
+
334
+ const tokens = await response.json();
335
+
336
+ this.accessToken = tokens.access_token;
337
+ this.refreshToken = tokens.refresh_token; // Update refresh token if provided
338
+ this.expiresAt = Date.now() + (tokens.expires_in * 1000);
339
+
340
+ return tokens;
341
+ } catch (error) {
342
+ console.error('Token refresh failed:', error);
343
+ throw error;
344
+ }
345
+ }
346
+ }
347
+
348
+ // Usage
349
+ const tokenManager = new AgilityTokenManager('your-refresh-token');
350
+ const token = await tokenManager.getValidToken();
351
+
352
+ const options = new mgmtApi.Options();
353
+ options.token = token;
354
+ const apiClient = new mgmtApi.ApiClient(options);
355
+ ```
356
+
357
+ ### Error Handling
358
+
359
+ #### Common Authentication Errors
360
+
361
+ ```javascript
362
+ async function makeAuthenticatedRequest() {
363
+ try {
364
+ const apiClient = new mgmtApi.ApiClient({ token: accessToken });
365
+ const result = await apiClient.contentMethods.getContentItem(123, guid, locale);
366
+ return result;
367
+ } catch (error) {
368
+ if (error.response?.status === 401) {
369
+ // Token expired or invalid
370
+ console.log('Authentication failed - refreshing token');
371
+ await refreshAccessToken();
372
+
373
+ // Retry the request
374
+ const apiClient = new mgmtApi.ApiClient({ token: newAccessToken });
375
+ return await apiClient.contentMethods.getContentItem(123, guid, locale);
376
+ } else if (error.response?.status === 403) {
377
+ // Insufficient permissions
378
+ console.error('Access denied - insufficient permissions');
379
+ throw new Error('User does not have permission for this operation');
380
+ } else {
381
+ // Other errors
382
+ console.error('API request failed:', error.message);
383
+ throw error;
384
+ }
385
+ }
386
+ }
387
+ ```
388
+
389
+ ### Migration Guide
390
+
391
+ #### Migrating from Manual OAuth to Simple Authentication
392
+
393
+ **Before (Manual OAuth):**
394
+ ```typescript
395
+ // Old approach - manual OAuth handling
396
+ import * as mgmtApi from '@agility/management-sdk';
397
+
398
+ const options = new mgmtApi.Options();
399
+ options.token = 'manually-obtained-token';
400
+ const apiClient = new mgmtApi.ApiClient(options);
401
+
402
+ // Manual token refresh required
403
+ const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
404
+ ```
405
+
406
+ **After (Simple Authentication):**
407
+ ```typescript
408
+ // New approach - automatic OAuth handling
409
+ import * as mgmtApi from '@agility/management-sdk';
410
+
411
+ const apiClient = new mgmtApi.ApiClient();
412
+ await apiClient.auth();
413
+
414
+ // Automatic token refresh handled internally
415
+ const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
416
+ ```
417
+
418
+ #### Migrating from AuthMethods Class
419
+
420
+ **Before (AuthMethods Class):**
421
+ ```typescript
422
+ import { AuthMethods } from '@agility/management-sdk';
423
+
424
+ const auth = new AuthMethods();
425
+ const client = auth.createAuthenticatedClient('token');
426
+ ```
427
+
428
+ **After (Simple Authentication):**
429
+ ```typescript
430
+ import * as mgmtApi from '@agility/management-sdk';
431
+
432
+ const apiClient = new mgmtApi.ApiClient();
433
+ await apiClient.auth();
434
+ ```
435
+
436
+ ### Advanced Features
437
+
438
+ #### Secure Token Storage
439
+ The new authentication system uses OS-level secure storage:
440
+
441
+ - **macOS**: Keychain Access
442
+ - **Windows**: Windows Credential Store
443
+ - **Linux**: libsecret (GNOME Keyring)
444
+
445
+ Tokens are encrypted and stored securely, with automatic cleanup on logout.
446
+
447
+ #### Automatic Token Refresh
448
+ The SDK now handles token refresh automatically:
449
+
450
+ ```typescript
451
+ const apiClient = new mgmtApi.ApiClient();
452
+ await apiClient.auth();
453
+
454
+ // Token refresh happens automatically on 401 errors
455
+ const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
456
+ // If token was expired, it gets refreshed transparently
457
+ ```
458
+
459
+ #### Custom OAuth Configuration
460
+ You can customize the OAuth flow:
461
+
462
+ ```typescript
463
+ const apiClient = new mgmtApi.ApiClient();
464
+ await apiClient.auth({
465
+ redirectUri: 'https://yourapp.com/custom-callback',
466
+ scope: 'openid profile email offline_access',
467
+ region: 'us' // or 'ca', 'eu', 'au', 'dev'
468
+ });
469
+ ```
470
+
471
+ #### Manual Token Exchange
472
+ For custom OAuth implementations:
473
+
474
+ ```typescript
475
+ const apiClient = new mgmtApi.ApiClient();
476
+
477
+ // Exchange authorization code for tokens
478
+ const tokens = await apiClient.exchangeCodeForToken({
479
+ code: 'authorization_code_from_callback',
480
+ redirectUri: 'https://yourapp.com/auth/callback'
481
+ });
482
+
483
+ // Tokens are automatically stored and used
484
+ ```
485
+
486
+ ### Best Practices
487
+
488
+ #### Security Considerations
489
+
490
+ 1. **Use secure token storage (automatic with new auth)**
491
+ ```typescript
492
+ // ✅ Recommended - automatic secure storage
493
+ const apiClient = new mgmtApi.ApiClient();
494
+ await apiClient.auth(); // Tokens stored securely in OS keychain
495
+
496
+ // ✅ CI/CD - manual token (for automated environments)
497
+ const options = new mgmtApi.Options();
498
+ options.token = process.env.AGILITY_ACCESS_TOKEN;
499
+ const apiClient = new mgmtApi.ApiClient(options);
500
+
501
+ // ❌ Bad - hardcoded tokens
502
+ options.token = 'your-secret-token'; // Never do this
503
+ ```
504
+
505
+ 2. **Leverage automatic token refresh**
506
+ ```typescript
507
+ // ✅ Automatic token refresh (new approach)
508
+ const apiClient = new mgmtApi.ApiClient();
509
+ await apiClient.auth();
510
+
511
+ // Token refresh happens automatically on 401 errors
512
+ const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
513
+ ```
514
+
515
+ 3. **Handle authentication errors gracefully**
516
+ ```typescript
517
+ const apiClient = new mgmtApi.ApiClient();
518
+
519
+ try {
520
+ await apiClient.auth();
521
+ const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
522
+ } catch (error) {
523
+ if (error.message.includes('OAuth flow requires manual implementation')) {
524
+ // Handle OAuth flow manually
525
+ console.log('Visit the OAuth URL to authenticate');
526
+ } else {
527
+ // Handle other auth errors
528
+ console.error('Authentication failed:', error);
529
+ }
530
+ }
531
+ ```
532
+
533
+ 4. **Clear tokens on logout**
534
+ ```typescript
535
+ const apiClient = new mgmtApi.ApiClient();
536
+ await apiClient.auth();
537
+
538
+ // ... use API client ...
539
+
540
+ // Clear tokens securely on logout
541
+ await apiClient.clearToken();
542
+ ```
543
+
544
+ #### Performance Optimization
545
+
546
+ 1. **Reuse API client instances**
547
+ ```javascript
548
+ // ✅ Good - single instance
549
+ const apiClient = new mgmtApi.ApiClient(options);
550
+
551
+ // Use the same instance for multiple requests
552
+ const content1 = await apiClient.contentMethods.getContentItem(1, guid, locale);
553
+ const content2 = await apiClient.contentMethods.getContentItem(2, guid, locale);
554
+ ```
555
+
556
+ 2. **Implement request caching**
557
+ ```javascript
558
+ class CachedAgilityClient {
559
+ constructor(options) {
560
+ this.client = new mgmtApi.ApiClient(options);
561
+ this.cache = new Map();
562
+ }
563
+
564
+ async getContentItem(id, guid, locale) {
565
+ const cacheKey = `content-${id}-${guid}-${locale}`;
566
+
567
+ if (this.cache.has(cacheKey)) {
568
+ return this.cache.get(cacheKey);
569
+ }
570
+
571
+ const result = await this.client.contentMethods.getContentItem(id, guid, locale);
572
+ this.cache.set(cacheKey, result);
573
+
574
+ return result;
575
+ }
576
+ }
577
+ ```
578
+
579
+ ---
580
+
581
+ ## Navigation
582
+ - [← Back to Main Documentation](../README.md)
583
+ - [CI/CD & Automated Environments](./cicd.md)
584
+ - [AssetMethods](./asset-methods.md)
585
+ - [BatchMethods](./batch-methods.md)
586
+ - [ContentMethods](./content-methods.md)
587
+ - [ContainerMethods](./container-methods.md)
588
+ - [InstanceMethods](./instance-methods.md)
589
+ - [InstanceUserMethods](./instance-user-methods.md)
590
+ - [ModelMethods](./model-methods.md)
591
+ - [PageMethods](./page-methods.md)
592
+ - [ServerUserMethods](./server-user-methods.md)
593
+ - [WebhookMethods](./webhook-methods.md)
594
594
  - [Multi-Instance Operations](./multi-instance-operations.md)