@agility/management-sdk 0.1.35 → 0.1.37

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 (261) hide show
  1. package/README.md +371 -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 +119 -48
  8. package/dist/apiMethods/pageMethods.d.ts +12 -0
  9. package/dist/apiMethods/pageMethods.js +88 -34
  10. package/dist/enums/contentViewType.d.ts +6 -0
  11. package/dist/enums/contentViewType.js +10 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +2 -0
  14. package/dist/models/pagedResult.d.ts +4 -0
  15. package/dist/models/pagedResult.js +2 -0
  16. package/dist/util/queryString.d.ts +8 -0
  17. package/dist/util/queryString.js +27 -0
  18. package/docs/asset-methods.md +381 -381
  19. package/docs/auth-component.md +360 -360
  20. package/docs/auth.md +593 -593
  21. package/docs/batch-methods.md +243 -243
  22. package/docs/cicd.md +606 -606
  23. package/docs/container-methods.md +267 -267
  24. package/docs/content-methods.md +491 -422
  25. package/docs/instance-methods.md +104 -104
  26. package/docs/instance-user-methods.md +230 -230
  27. package/docs/model-methods.md +433 -433
  28. package/docs/multi-instance-operations.md +191 -191
  29. package/docs/page-methods.md +737 -670
  30. package/docs/server-user-methods.md +279 -279
  31. package/docs/webhook-methods.md +451 -451
  32. package/license.txt +20 -20
  33. package/package.json +40 -40
  34. package/tsconfig.json +14 -14
  35. package/.cursor/api-coverage.md +0 -217
  36. package/.cursor/api-documentation-manifest.md +0 -275
  37. package/.cursor/api-functions-analysis.md +0 -111
  38. package/.cursor/breakout-manifest.md +0 -278
  39. package/.cursor/docs-final-check.md +0 -269
  40. package/.cursor/github-actions-improvements.md +0 -76
  41. package/.cursor/hardening.md +0 -271
  42. package/.cursor/linting-fix.md +0 -160
  43. package/.cursor/manifest.md +0 -243
  44. package/.cursor/mocks.md +0 -100
  45. package/.cursor/test-coverage.md +0 -841
  46. package/.env +0 -92
  47. package/coverage/base.css +0 -224
  48. package/coverage/block-navigation.js +0 -87
  49. package/coverage/coverage-summary.json +0 -43
  50. package/coverage/favicon.png +0 -0
  51. package/coverage/index.html +0 -161
  52. package/coverage/lcov-report/base.css +0 -224
  53. package/coverage/lcov-report/block-navigation.js +0 -87
  54. package/coverage/lcov-report/favicon.png +0 -0
  55. package/coverage/lcov-report/index.html +0 -161
  56. package/coverage/lcov-report/prettify.css +0 -1
  57. package/coverage/lcov-report/prettify.js +0 -2
  58. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  59. package/coverage/lcov-report/sorter.js +0 -210
  60. package/coverage/lcov-report/src/apiClient.ts.html +0 -199
  61. package/coverage/lcov-report/src/apiMethods/assetMethods.ts.html +0 -682
  62. package/coverage/lcov-report/src/apiMethods/batchMethods.ts.html +0 -736
  63. package/coverage/lcov-report/src/apiMethods/clientInstance.ts.html +0 -403
  64. package/coverage/lcov-report/src/apiMethods/containerMethods.ts.html +0 -460
  65. package/coverage/lcov-report/src/apiMethods/contentMethods.ts.html +0 -1183
  66. package/coverage/lcov-report/src/apiMethods/index.html +0 -266
  67. package/coverage/lcov-report/src/apiMethods/instanceMethods.ts.html +0 -160
  68. package/coverage/lcov-report/src/apiMethods/instanceUserMethods.ts.html +0 -268
  69. package/coverage/lcov-report/src/apiMethods/modelMethods.ts.html +0 -352
  70. package/coverage/lcov-report/src/apiMethods/pageMethods.ts.html +0 -1276
  71. package/coverage/lcov-report/src/apiMethods/serverUserMethods.ts.html +0 -196
  72. package/coverage/lcov-report/src/apiMethods/webhookMethods.ts.html +0 -271
  73. package/coverage/lcov-report/src/enums/batchItemType.ts.html +0 -106
  74. package/coverage/lcov-report/src/enums/batchOperationType.ts.html +0 -142
  75. package/coverage/lcov-report/src/enums/batchState..ts.html +0 -106
  76. package/coverage/lcov-report/src/enums/index.html +0 -161
  77. package/coverage/lcov-report/src/enums/workflowOperationType.ts.html +0 -175
  78. package/coverage/lcov-report/src/index.html +0 -116
  79. package/coverage/lcov-report/src/models/assetContainer.ts.html +0 -106
  80. package/coverage/lcov-report/src/models/assetGalleries.ts.html +0 -103
  81. package/coverage/lcov-report/src/models/assetMediaGrouping.ts.html +0 -136
  82. package/coverage/lcov-report/src/models/assetMediaGroupingMetaData.ts.html +0 -97
  83. package/coverage/lcov-report/src/models/batch.ts.html +0 -178
  84. package/coverage/lcov-report/src/models/batchItem.ts.html +0 -127
  85. package/coverage/lcov-report/src/models/container.ts.html +0 -232
  86. package/coverage/lcov-report/src/models/contentDefinitionTypeID.ts.html +0 -142
  87. package/coverage/lcov-report/src/models/contentItem.ts.html +0 -202
  88. package/coverage/lcov-report/src/models/contentSectionDefaultModule.ts.html +0 -106
  89. package/coverage/lcov-report/src/models/contentSectionDefinition.ts.html +0 -196
  90. package/coverage/lcov-report/src/models/contentViewColumn.ts.html +0 -109
  91. package/coverage/lcov-report/src/models/exception.ts.html +0 -109
  92. package/coverage/lcov-report/src/models/index.html +0 -476
  93. package/coverage/lcov-report/src/models/instanceRole.ts.html +0 -106
  94. package/coverage/lcov-report/src/models/instanceUser.ts.html +0 -130
  95. package/coverage/lcov-report/src/models/locales.ts.html +0 -100
  96. package/coverage/lcov-report/src/models/media.ts.html +0 -178
  97. package/coverage/lcov-report/src/models/model.ts.html +0 -172
  98. package/coverage/lcov-report/src/models/notification.ts.html +0 -124
  99. package/coverage/lcov-report/src/models/options.ts.html +0 -109
  100. package/coverage/lcov-report/src/models/pageItem.ts.html +0 -268
  101. package/coverage/lcov-report/src/models/pageModel.ts.html +0 -130
  102. package/coverage/lcov-report/src/models/sharedModule.ts.html +0 -106
  103. package/coverage/lcov-report/src/models/sitemap.ts.html +0 -148
  104. package/coverage/lcov-report/src/models/websiteUser.ts.html +0 -157
  105. package/coverage/lcov.info +0 -1459
  106. package/coverage/prettify.css +0 -1
  107. package/coverage/prettify.js +0 -2
  108. package/coverage/sort-arrow-sprite.png +0 -0
  109. package/coverage/sorter.js +0 -210
  110. package/coverage/src/apiClient.ts.html +0 -199
  111. package/coverage/src/apiMethods/assetMethods.ts.html +0 -682
  112. package/coverage/src/apiMethods/batchMethods.ts.html +0 -736
  113. package/coverage/src/apiMethods/clientInstance.ts.html +0 -403
  114. package/coverage/src/apiMethods/containerMethods.ts.html +0 -460
  115. package/coverage/src/apiMethods/contentMethods.ts.html +0 -1183
  116. package/coverage/src/apiMethods/index.html +0 -266
  117. package/coverage/src/apiMethods/instanceMethods.ts.html +0 -160
  118. package/coverage/src/apiMethods/instanceUserMethods.ts.html +0 -268
  119. package/coverage/src/apiMethods/modelMethods.ts.html +0 -352
  120. package/coverage/src/apiMethods/pageMethods.ts.html +0 -1276
  121. package/coverage/src/apiMethods/serverUserMethods.ts.html +0 -196
  122. package/coverage/src/apiMethods/webhookMethods.ts.html +0 -271
  123. package/coverage/src/enums/batchItemType.ts.html +0 -106
  124. package/coverage/src/enums/batchOperationType.ts.html +0 -142
  125. package/coverage/src/enums/batchState..ts.html +0 -106
  126. package/coverage/src/enums/index.html +0 -161
  127. package/coverage/src/enums/workflowOperationType.ts.html +0 -175
  128. package/coverage/src/index.html +0 -116
  129. package/coverage/src/models/assetContainer.ts.html +0 -106
  130. package/coverage/src/models/assetGalleries.ts.html +0 -103
  131. package/coverage/src/models/assetMediaGrouping.ts.html +0 -136
  132. package/coverage/src/models/assetMediaGroupingMetaData.ts.html +0 -97
  133. package/coverage/src/models/batch.ts.html +0 -178
  134. package/coverage/src/models/batchItem.ts.html +0 -127
  135. package/coverage/src/models/container.ts.html +0 -232
  136. package/coverage/src/models/contentDefinitionTypeID.ts.html +0 -142
  137. package/coverage/src/models/contentItem.ts.html +0 -202
  138. package/coverage/src/models/contentSectionDefaultModule.ts.html +0 -106
  139. package/coverage/src/models/contentSectionDefinition.ts.html +0 -196
  140. package/coverage/src/models/contentViewColumn.ts.html +0 -109
  141. package/coverage/src/models/exception.ts.html +0 -109
  142. package/coverage/src/models/index.html +0 -476
  143. package/coverage/src/models/instanceRole.ts.html +0 -106
  144. package/coverage/src/models/instanceUser.ts.html +0 -130
  145. package/coverage/src/models/locales.ts.html +0 -100
  146. package/coverage/src/models/media.ts.html +0 -178
  147. package/coverage/src/models/model.ts.html +0 -172
  148. package/coverage/src/models/notification.ts.html +0 -124
  149. package/coverage/src/models/options.ts.html +0 -109
  150. package/coverage/src/models/pageItem.ts.html +0 -268
  151. package/coverage/src/models/pageModel.ts.html +0 -130
  152. package/coverage/src/models/sharedModule.ts.html +0 -106
  153. package/coverage/src/models/sitemap.ts.html +0 -148
  154. package/coverage/src/models/websiteUser.ts.html +0 -157
  155. package/dist/.tsbuildinfo +0 -1
  156. package/dist/apiClient.d.ts.map +0 -1
  157. package/dist/apiClient.js.map +0 -1
  158. package/dist/apiMethods/assetMethods.d.ts.map +0 -1
  159. package/dist/apiMethods/assetMethods.js.map +0 -1
  160. package/dist/apiMethods/batchMethods.d.ts.map +0 -1
  161. package/dist/apiMethods/batchMethods.js.map +0 -1
  162. package/dist/apiMethods/clientInstance.d.ts.map +0 -1
  163. package/dist/apiMethods/clientInstance.js.map +0 -1
  164. package/dist/apiMethods/containerMethods.d.ts.map +0 -1
  165. package/dist/apiMethods/containerMethods.js.map +0 -1
  166. package/dist/apiMethods/contentMethods.d.ts.map +0 -1
  167. package/dist/apiMethods/contentMethods.js.map +0 -1
  168. package/dist/apiMethods/instanceMethods.d.ts.map +0 -1
  169. package/dist/apiMethods/instanceMethods.js.map +0 -1
  170. package/dist/apiMethods/instanceUserMethods.d.ts.map +0 -1
  171. package/dist/apiMethods/instanceUserMethods.js.map +0 -1
  172. package/dist/apiMethods/modelMethods.d.ts.map +0 -1
  173. package/dist/apiMethods/modelMethods.js.map +0 -1
  174. package/dist/apiMethods/pageMethods.d.ts.map +0 -1
  175. package/dist/apiMethods/pageMethods.js.map +0 -1
  176. package/dist/apiMethods/serverUserMethods.d.ts.map +0 -1
  177. package/dist/apiMethods/serverUserMethods.js.map +0 -1
  178. package/dist/apiMethods/webhookMethods.d.ts.map +0 -1
  179. package/dist/apiMethods/webhookMethods.js.map +0 -1
  180. package/dist/enums/assetGroupingType.d.ts.map +0 -1
  181. package/dist/enums/assetGroupingType.js.map +0 -1
  182. package/dist/enums/batchItemType.d.ts.map +0 -1
  183. package/dist/enums/batchItemType.js.map +0 -1
  184. package/dist/enums/batchOperationType.d.ts.map +0 -1
  185. package/dist/enums/batchOperationType.js.map +0 -1
  186. package/dist/enums/batchState..d.ts.map +0 -1
  187. package/dist/enums/batchState..js.map +0 -1
  188. package/dist/enums/pageItemTemplateType.d.ts.map +0 -1
  189. package/dist/enums/pageItemTemplateType.js.map +0 -1
  190. package/dist/enums/workflowOperationType.d.ts.map +0 -1
  191. package/dist/enums/workflowOperationType.js.map +0 -1
  192. package/dist/index.d.ts.map +0 -1
  193. package/dist/index.js.map +0 -1
  194. package/dist/models/assetContainer.d.ts.map +0 -1
  195. package/dist/models/assetContainer.js.map +0 -1
  196. package/dist/models/assetGalleries.d.ts.map +0 -1
  197. package/dist/models/assetGalleries.js.map +0 -1
  198. package/dist/models/assetMediaGrouping.d.ts.map +0 -1
  199. package/dist/models/assetMediaGrouping.js.map +0 -1
  200. package/dist/models/assetMediaGroupingMetaData.d.ts.map +0 -1
  201. package/dist/models/assetMediaGroupingMetaData.js.map +0 -1
  202. package/dist/models/batch.d.ts.map +0 -1
  203. package/dist/models/batch.js.map +0 -1
  204. package/dist/models/batchItem.d.ts.map +0 -1
  205. package/dist/models/batchItem.js.map +0 -1
  206. package/dist/models/batchTypes.d.ts.map +0 -1
  207. package/dist/models/batchTypes.js.map +0 -1
  208. package/dist/models/container.d.ts.map +0 -1
  209. package/dist/models/container.js.map +0 -1
  210. package/dist/models/contentDefinitionTypeID.d.ts.map +0 -1
  211. package/dist/models/contentDefinitionTypeID.js.map +0 -1
  212. package/dist/models/contentItem.d.ts.map +0 -1
  213. package/dist/models/contentItem.js.map +0 -1
  214. package/dist/models/contentItemHistory.d.ts.map +0 -1
  215. package/dist/models/contentItemHistory.js.map +0 -1
  216. package/dist/models/contentListFilterModel.d.ts.map +0 -1
  217. package/dist/models/contentListFilterModel.js.map +0 -1
  218. package/dist/models/contentSectionDefaultModule.d.ts.map +0 -1
  219. package/dist/models/contentSectionDefaultModule.js.map +0 -1
  220. package/dist/models/contentSectionDefinition.d.ts.map +0 -1
  221. package/dist/models/contentSectionDefinition.js.map +0 -1
  222. package/dist/models/contentViewColumn.d.ts.map +0 -1
  223. package/dist/models/contentViewColumn.js.map +0 -1
  224. package/dist/models/exception.d.ts.map +0 -1
  225. package/dist/models/exception.js.map +0 -1
  226. package/dist/models/instanceRole.d.ts.map +0 -1
  227. package/dist/models/instanceRole.js.map +0 -1
  228. package/dist/models/instanceUser.d.ts.map +0 -1
  229. package/dist/models/instanceUser.js.map +0 -1
  230. package/dist/models/itemComments.d.ts.map +0 -1
  231. package/dist/models/itemComments.js.map +0 -1
  232. package/dist/models/listParams.d.ts.map +0 -1
  233. package/dist/models/listParams.js.map +0 -1
  234. package/dist/models/locales.d.ts.map +0 -1
  235. package/dist/models/locales.js.map +0 -1
  236. package/dist/models/media.d.ts.map +0 -1
  237. package/dist/models/media.js.map +0 -1
  238. package/dist/models/model.d.ts.map +0 -1
  239. package/dist/models/model.js.map +0 -1
  240. package/dist/models/notification.d.ts.map +0 -1
  241. package/dist/models/notification.js.map +0 -1
  242. package/dist/models/options.d.ts.map +0 -1
  243. package/dist/models/options.js.map +0 -1
  244. package/dist/models/pageHistory.d.ts.map +0 -1
  245. package/dist/models/pageHistory.js.map +0 -1
  246. package/dist/models/pageItem.d.ts.map +0 -1
  247. package/dist/models/pageItem.js.map +0 -1
  248. package/dist/models/pageModel.d.ts.map +0 -1
  249. package/dist/models/pageModel.js.map +0 -1
  250. package/dist/models/serverUser.d.ts.map +0 -1
  251. package/dist/models/serverUser.js.map +0 -1
  252. package/dist/models/sharedModule.d.ts.map +0 -1
  253. package/dist/models/sharedModule.js.map +0 -1
  254. package/dist/models/sitemap.d.ts.map +0 -1
  255. package/dist/models/sitemap.js.map +0 -1
  256. package/dist/models/webhook.d.ts.map +0 -1
  257. package/dist/models/webhook.js.map +0 -1
  258. package/dist/models/websiteListing.d.ts.map +0 -1
  259. package/dist/models/websiteListing.js.map +0 -1
  260. package/dist/models/websiteUser.d.ts.map +0 -1
  261. 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)