From ca969f406a04d3b919705ec9924c7b9e83cbff47 Mon Sep 17 00:00:00 2001 From: Thomas Millward Wright Date: Mon, 10 Mar 2025 17:53:42 +0000 Subject: [PATCH 1/3] [LA-25920] update docs wrt scopes --- source/includes/_activities.md | 3 + source/includes/_authentication.md | 81 +++++- source/includes/_channels.md | 6 + source/includes/_communities.md | 3 + source/includes/_enrollments.md | 84 +++++- source/includes/_events.md | 5 + source/includes/_items.md | 13 + source/includes/_learnlists.md | 3 + source/includes/_tasks.md | 3 + source/includes/_team_users.md | 451 ++++++----------------------- source/includes/_teams.md | 11 + source/includes/_users.md | 22 +- source/includes/_verbs.md | 5 +- 13 files changed, 308 insertions(+), 382 deletions(-) diff --git a/source/includes/_activities.md b/source/includes/_activities.md index 9b44676b2ec..ba99c09ce4a 100644 --- a/source/includes/_activities.md +++ b/source/includes/_activities.md @@ -57,6 +57,9 @@ View all activity `GET https://{API_BASE_URL}/v1/activities` +### Required Scope +This endpoint requires the `activities:read` scope. + Response will be paginated [see pagination](#pagination) diff --git a/source/includes/_authentication.md b/source/includes/_authentication.md index d36185e4897..77b1e0977fb 100644 --- a/source/includes/_authentication.md +++ b/source/includes/_authentication.md @@ -69,4 +69,83 @@ Subsequent API calls then require this access token to be present in an **Author \ No newline at end of file + + +## OAuth Scopes + +The Learn Amp API uses OAuth 2.0 scopes to control access to different parts of the API. When requesting an access token, you can specify which scopes you need access to. + +By default, tokens are issued with the `public` scope, which provides basic access. For more specific operations, you should request additional scopes. + +Legacy scopes are created with full access, and implicitly request and are granted the `public` scope. Moving forward, API credentials should be provisioned with the specific scopes they require. + +### Available Scopes + +Scope | Description +--------- | ----------- +public | Basic access scope - included by default +items:read | Read access to items +items:create | Create new items +items:update | Update existing items +items:delete | Delete items +items:complete | Mark items as complete +activities:read | Read access to activities +enrollments:read | Read access to enrollments +enrollments:create | Create new enrollments +events:read | Read access to events +teams:read | Read access to teams +teams:create | Create new teams +teams:update | Update existing teams +teams:delete | Delete teams +team_users:read | Read access to team users +team_users:create | Add users to teams +team_users:delete | Remove users from teams +users:read | Read access to users +users:create | Create new users +users:update | Update existing users +users:delete | Delete users +users:deactivate | Deactivate users +users:reactivate | Reactivate users +communities:read | Read access to communities +tasks:read | Read access to tasks +verbs:read | Read access to verbs +languages:read | Read access to languages +learnlists:read | Read access to learnlists +channels:read | Read access to channels +channel_users_progress:read | Read access to channel users progress +user_channels_progress:read | Read access to user channels progress +roles:read | Read access to roles + +### Requesting Scopes + +To request specific scopes, add the `scope` parameter to your token request: + +```shell +curl --location --request POST 'https://api.learnamp.com/oauth/token' \ +--form 'client_id=YOUR-CLIENT-ID' \ +--form 'client_secret=YOUR-CLIENT-SECRET' \ +--form 'grant_type=client_credentials' \ +--form 'scope=items:read items:create' +``` + +```ruby +module Learnamp + class Auth + include HTTParty + base_uri ENV['BASE_URL'] + + def self.access_token + post('/oauth/token', + body: { + grant_type: 'client_credentials', + client_id: ENV['CLIENT_ID'], + client_secret: ENV['CLIENT_SECRET'], + scope: 'items:read items:create' + }) + end + end +end + +response = Learnamp::Auth.access_token +puts response["access_token"] if response.ok? +``` diff --git a/source/includes/_channels.md b/source/includes/_channels.md index f355c2b01e5..9b019828d70 100644 --- a/source/includes/_channels.md +++ b/source/includes/_channels.md @@ -50,6 +50,9 @@ View all channels `GET https://{API_BASE_URL}/v1/channels` +### Required Scope +This endpoint requires the `channels:read` scope. + Response will be paginated [see pagination](#pagination) > 200 OK - successful response: @@ -109,6 +112,9 @@ View progress of all assigned users through a specified channel. This is analogo `GET https://{API_BASE_URL}/v1/channels/{channelId}/users_progress` +### Required Scope +This endpoint requires the `channel_users_progress:read` scope. + This end-point will return a paginated array of users who are assigned the specified channel. Each element will contain the completion percentage of the channel by that user, as well as the datetime (if any) when the channel was completed. Please note: Only assigned users will be returned. Users who are not assigned the specified channel will not appear in the array. diff --git a/source/includes/_communities.md b/source/includes/_communities.md index 9be792a2e7f..f01748a5ad3 100644 --- a/source/includes/_communities.md +++ b/source/includes/_communities.md @@ -47,6 +47,9 @@ View all community posts `GET https://{API_BASE_URL}/v1/communities/:id/posts` +### Required Scope +This endpoint requires the `communities_posts:read` scope. + Response will be paginated [see pagination](#pagination) diff --git a/source/includes/_enrollments.md b/source/includes/_enrollments.md index 9240bb10c9a..63f10d4ccfc 100644 --- a/source/includes/_enrollments.md +++ b/source/includes/_enrollments.md @@ -53,6 +53,9 @@ View all events `GET https://{API_BASE_URL}/v1/enrollments` +### Required Scope +This endpoint requires the `enrollments:read` scope. + Response will be paginated [see pagination](#pagination) @@ -191,8 +194,10 @@ event = Learnamp::Events.new(token).find(1) Display user details for one specific event. -`GET https://{API_BASE_URL}/v1/event/{eventId}` +`GET https://{API_BASE_URL}/v1/events/{eventId}` +### Required Scope +This endpoint requires the `events:read` scope. > 200 OK - successful response: @@ -267,16 +272,16 @@ Display user details for one specific event. ## Show an Enrollment -> Display details for a single enrollment: +> Show a specific enrollment: ```shell -curl --location --request GET 'https://api.learnamp.com/v1/enrollments/1' \ +curl --location --request GET 'https://api.learnamp.com/v1/enrollments/52' \ --header 'Authorization: Bearer YOUR-ACCESS-TOKEN' ``` ```ruby module Learnamp - class Users + class Enrollments include HTTParty base_uri "#{ENV['BASE_URL']}#{ENV['API_PATH']}" @@ -288,7 +293,7 @@ module Learnamp def find(id) response = self.class.get("/enrollments/#{id}", { headers: headers }) - response.parsed_response if response.ok? + response.parsed_response end private @@ -301,13 +306,15 @@ module Learnamp end end -enrollment = Learnamp::Enrollments.new(token).find(1) +enrollment = Learnamp::Enrollments.new(token).find(52) ``` -Display user details for one specific user. +Shows details of an enrollment. -`GET https://{API_BASE_URL}/v1/enrollments/{enrollmentId}` +`GET https://{API_BASE_URL}/v1/enrollments/{id}` +### Required Scope +This endpoint requires the `enrollments:read` scope. > 200 OK - successful response: @@ -382,4 +389,63 @@ Display user details for one specific user. { "error": "Not found" } -``` \ No newline at end of file +``` + +## Create an Enrollment + +> Create a new enrollment: + +```shell +curl --location --request POST 'https://api.learnamp.com/v1/enrollments' \ +--header 'Authorization: Bearer YOUR-ACCESS-TOKEN' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "user_id": 1, + "event_name": "Leadership workshop", + "event_session_id": 5 +}' +``` + +```ruby +module Learnamp + class Enrollments + include HTTParty + base_uri "#{ENV['BASE_URL']}#{ENV['API_PATH']}" + + attr_accessor :token + + def initialize(token) + @token = token + end + + def create(params) + response = self.class.post("/enrollments", { body: params, headers: headers }) + response.parsed_response + end + + private + + def headers + { + 'Authorization' => "Bearer #{token}", + 'Content-Type' => 'application/json' + } + end + end +end + +params = { + user_id: 1, + event_name: "Leadership workshop", + event_session_id: 5 +} + +enrollments = Learnamp::Enrollments.new(token).create(params) +``` + +Creates a new enrollment. This will enrol a given user into an event session. By default, the new enrollment will have a status of 'approved'. + +`POST https://{API_BASE_URL}/v1/enrollments` + +### Required Scope +This endpoint requires the `enrollments:create` scope. diff --git a/source/includes/_events.md b/source/includes/_events.md index f8222df8e95..0547e6757ce 100644 --- a/source/includes/_events.md +++ b/source/includes/_events.md @@ -57,6 +57,9 @@ View all events `GET https://{API_BASE_URL}/v1/events` +### Required Scope +This endpoint requires the `events:read` scope. + Response will be paginated [see pagination](#pagination) @@ -151,6 +154,8 @@ Display user details for one specific event. `GET https://{API_BASE_URL}/v1/events/{eventId}` +### Required Scope +This endpoint requires the `events:read` scope. > 200 OK - successful response: diff --git a/source/includes/_items.md b/source/includes/_items.md index 56c624b9a1b..429494fca2f 100644 --- a/source/includes/_items.md +++ b/source/includes/_items.md @@ -47,6 +47,9 @@ View all items `GET https://{API_BASE_URL}/v1/items` +### Required Scope +This endpoint requires the `items:read` scope. + Response will be paginated [see pagination](#pagination) > 200 OK - successful response: @@ -118,6 +121,8 @@ Display all details for one specific Item. `GET https://{API_BASE_URL}/v1/items/{itemId}` +### Required Scope +This endpoint requires the `items:read` scope. > 200 OK - successful response: @@ -239,6 +244,9 @@ Create an Item `POST https://{API_BASE_URL}/v1/items` +### Required Scope +This endpoint requires the `items:create` scope. + ### Data in Body Parameter (* required) | Example value | Description @@ -395,6 +403,9 @@ Update an Item `PUT https://{API_BASE_URL}/v1/items/{itemId}` +### Required Scope +This endpoint requires the `items:update` scope. + ### Data in Body Parameter (* required) | Example value | Description @@ -669,6 +680,8 @@ Delete an Item `DELETE https://{API_BASE_URL}/v1/items/{itemId}` +### Required Scope +This endpoint requires the `items:delete` scope. > 204 No Content - successful response: diff --git a/source/includes/_learnlists.md b/source/includes/_learnlists.md index 3cc6a6365e1..4c7aa5feb23 100644 --- a/source/includes/_learnlists.md +++ b/source/includes/_learnlists.md @@ -50,6 +50,9 @@ View all learnlists `GET https://{API_BASE_URL}/v1/learnlists` +### Required Scope +This endpoint requires the `learnlists:read` scope. + Response will be paginated [see pagination](#pagination) > 200 OK - successful response: diff --git a/source/includes/_tasks.md b/source/includes/_tasks.md index 3d7b2f7590c..092ea4b9960 100644 --- a/source/includes/_tasks.md +++ b/source/includes/_tasks.md @@ -74,6 +74,9 @@ View all tasks `GET https://{API_BASE_URL}/v1/tasks` +### Required Scope +This endpoint requires the `tasks:read` scope. + Response will be paginated [see pagination](#pagination) diff --git a/source/includes/_team_users.md b/source/includes/_team_users.md index 1a3ba5cd2a6..55edf55bf7f 100644 --- a/source/includes/_team_users.md +++ b/source/includes/_team_users.md @@ -1,8 +1,8 @@ # Team Users -## View all users in a Team +## View All Team Users -> View all users in a specific team: +> View all users for a given team: ```shell curl --location --request GET 'https://api.learnamp.com/v1/teams/1/users' \ @@ -21,7 +21,7 @@ module Learnamp @token = token end - def find(team_id) + def all(team_id) response = self.class.get("/teams/#{team_id}/users", { headers: headers }) response.parsed_response end @@ -36,100 +36,19 @@ module Learnamp end end -users = Learnamp::TeamUsers.new(token).find(245) +team_users = Learnamp::TeamUsers.new(token).all(1) ``` -View a specific team, and include all users in that team. - -`GET https://{API_BASE_URL}/v1/teams/{teamId}/users` - -> 200 OK - successful response: - -```json -{ - - "id": 379, - "name": "Test Team", - "teamUsersCount": 2, - "apiTeamPath": "/v1/teams/379.json", - "apiTeamUsersPath": "/v1/teams/379/users.json", - "manager": { - "id": 7, - "firstName": "Test", - "lastName": "Manager", - "jobTitle": "Ops Director", - "email": "admin@example.com", - "timeZone": "London", - "language": "en", - "role": "admin", - "profileUrl": "http://testaccount.learnamp.com/en/users/7", - "status": { - "status": "Invite pending", - "time": "Sent 25 Sep 19" - } - }, - "users": [ - { - "id": 1, - "firstName": "Test", - "lastName": "User", - "jobTitle": "Developer", - "email": "test@email.com", - "timeZone": "London", - "language": "en", - "role": "viewer", - "profileUrl": "https://testaccount.learnamp.com/en/users/1", - "status": { - "status": "Confirmed", - "time": "On 29 Nov 16" - }, - "avatar": "AVATAR_IMAGE_URL", - "manager": { - "id": 17, - "firstName": "Manager", - "lastName": "User", - "jobTitle": "Head of Ops", - "email": "testuser2@email.com", - "timeZone": "New York", - "language": "en-US", - "role": "admin", - "profileUrl": "https://testaccount.learnamp.com/en/users/17", - "status": { - "status": "Confirmed", - "time": "On 20 Feb 17" - } - }, - "location": "London, UK", - "primaryTeam": { - "id": 15, - "name": "Operations", - "teamUsersCount": 10, - "apiTeamPath": "/v1/teams/15.json", - "apiTeamUsersPath": "/v1/teams/15/users.json", - "manager": { - "id": 17, - "firstName": "Manager", - "lastName": "User", - "jobTitle": "Head of Ops", - "email": "testuser2@email.com", - "timeZone": "New York", - "language": "en-US", - "role": "admin", - "profileUrl": "https://testaccount.learnamp.com/en/users/17", - "status": { - "status": "Confirmed", - "time": "On 20 Feb 17" - } - } - }, - "secondaryTeams": [] - }, - ] - } - ] -} +View all users for a given team. -``` +### HTTP Request + +`GET https://{API_BASE_URL}/v1/teams/{team_id}/users` + +### Required Scope +This endpoint requires the `team_users:read` scope. + +Response will be paginated [see pagination](#pagination) ## Add a User to a Team @@ -138,7 +57,11 @@ View a specific team, and include all users in that team. ```shell curl --location --request POST 'https://api.learnamp.com/v1/teams/1/users' \ --header 'Authorization: Bearer YOUR-ACCESS-TOKEN' \ ---form 'userId=1' +--header 'Content-Type: application/json' \ +--data-raw '{ + "userId": 1, + "isPrimary": true +}' ``` ```ruby @@ -153,8 +76,13 @@ module Learnamp @token = token end - def create(team_id, params) - response = self.class.post("/teams/#{team_id}/users", { body: params, headers: headers }) + def add(team_id, user_details) + response = self.class.post("/teams/#{team_id}/users", + { + headers: headers, + body: user_details.to_json + } + ) response.parsed_response end @@ -162,142 +90,37 @@ module Learnamp def headers { - 'Authorization' => "Bearer #{token}" + 'Authorization' => "Bearer #{token}", + 'Content-Type' => 'application/json' } end end end -params = { - userId: 1 +user_details = { + userId: 1, + isPrimary: true } -Learnamp::TeamUsers.new(token).create(245, params) +result = Learnamp::TeamUsers.new(token).add(1, user_details) ``` -Adds a user to a Team. - -`POST https://{API_BASE_URL}/v1/teams/{teamId}/users` - -Note that Team ID is passed in as a URL segment. - -### Data in Body - -Parameter | Example value | Description (* required) ---------- | ------- | ----------- -userId | 1 | User ID of user to add to team - -> 201 Created - successful response: - -```json -```json -{ - - "id": 1, - "name": "Test Team", - "teamUsersCount": 2, - "apiTeamPath": "/v1/teams/1.json", - "apiTeamUsersPath": "/v1/teams/1/users.json", - "manager": { - "id": 7, - "firstName": "Test", - "lastName": "Manager", - "jobTitle": "Ops Director", - "email": "admin@example.com", - "timeZone": "London", - "language": "en", - "role": "admin", - "profileUrl": "http://testaccount.learnamp.com/en/users/7", - "status": { - "status": "Invite pending", - "time": "Sent 25 Sep 19" - } - }, - "users": [ - { - "id": 1, - "firstName": "Test", - "lastName": "User", - "jobTitle": "Developer", - "email": "test@email.com", - "timeZone": "London", - "language": "en", - "role": "viewer", - "profileUrl": "https://testaccount.learnamp.com/en/users/1", - "status": { - "status": "Confirmed", - "time": "On 29 Nov 16" - }, - "avatar": "AVATAR_IMAGE_URL", - "manager": { - "id": 17, - "firstName": "Manager", - "lastName": "User", - "jobTitle": "Head of Ops", - "email": "testuser2@email.com", - "timeZone": "New York", - "language": "en-US", - "role": "admin", - "profileUrl": "https://testaccount.learnamp.com/en/users/17", - "status": { - "status": "Confirmed", - "time": "On 20 Feb 17" - } - }, - "location": "London, UK", - "primaryTeam": { - "id": 15, - "name": "Operations", - "teamUsersCount": 10, - "apiTeamPath": "/v1/teams/15.json", - "apiTeamUsersPath": "/v1/teams/15/users.json", - "manager": { - "id": 17, - "firstName": "Manager", - "lastName": "User", - "jobTitle": "Head of Ops", - "email": "testuser2@email.com", - "timeZone": "New York", - "language": "en-US", - "role": "admin", - "profileUrl": "https://testaccount.learnamp.com/en/users/17", - "status": { - "status": "Confirmed", - "time": "On 20 Feb 17" - } - } - }, - "secondaryTeams": [] - }, - ] - } - ] -} +Add a user to a team. -``` -``` +### HTTP Request -> 400 Bad request - validation errors: - -```json -{ - "error": "userId is missing, userId is empty", - "fullErrors": { - "userId": [ - "is missing", - "is empty" - ] - } -} -``` +`POST https://{API_BASE_URL}/v1/teams/{team_id}/users` + +### Required Scope +This endpoint requires the `team_users:create` scope. + +## Remove a User from a Team -## Add a User to a Team - second version +> Remove a user from a team: ```shell -curl --location --request POST 'https://api.learnamp.com/v1/teams/users' \ ---header 'Authorization: Bearer YOUR-ACCESS-TOKEN' \ ---form 'teamName=Marketing' ---form 'userEmail=new@member.com' +curl --location --request DELETE 'https://api.learnamp.com/v1/teams/1/users/1' \ +--header 'Authorization: Bearer YOUR-ACCESS-TOKEN' ``` ```ruby @@ -312,9 +135,9 @@ module Learnamp @token = token end - def create(params) - response = self.class.post('/teams/users', { body: params, headers: headers }) - response.parsed_response + def remove(team_id, user_id) + response = self.class.delete("/teams/#{team_id}/users/#{user_id}", { headers: headers }) + response.ok? end private @@ -327,143 +150,30 @@ module Learnamp end end -params = { - userEmail: 'user@email.com', - teamName: 'Tech Team' -} - -Learnamp::TeamUsers.new(token).create(params) +success = Learnamp::TeamUsers.new(token).remove(1, 1) ``` -Adds a user to a Team. - -In order to simplify integration with third party services, another -endpoint responsible for team member creation was implemented. - -`POST https://{API_BASE_URL}/v1/teams/users` - -### Data in Body - -Parameter | Example value | Description (* required) ---------- | ------- | ----------- -teamId | 1200 | ID of the team -teamName | "Marketing" | Name of the team -userId | 1 | User ID of user to add to team -userEmail | "user@email.com" | Email of the new team member - -Parameters `teamId` and `teamName` are mutually exclusive - only one of them can be present in the request payload. Same rule applies for `userId` and `userEmail`. - -> 201 Created - successful response: - -```json -```json -{ - - "id": 1, - "name": "Test Team", - "teamUsersCount": 2, - "apiTeamPath": "/v1/teams/1.json", - "apiTeamUsersPath": "/v1/teams/1/users.json", - "manager": { - "id": 7, - "firstName": "Test", - "lastName": "Manager", - "jobTitle": "Ops Director", - "email": "admin@example.com", - "timeZone": "London", - "language": "en", - "role": "admin", - "profileUrl": "http://testaccount.learnamp.com/en/users/7", - "status": { - "status": "Invite pending", - "time": "Sent 25 Sep 19" - } - }, - "users": [ - { - "id": 1, - "firstName": "Test", - "lastName": "User", - "jobTitle": "Developer", - "email": "test@email.com", - "timeZone": "London", - "language": "en", - "role": "viewer", - "profileUrl": "https://testaccount.learnamp.com/en/users/1", - "status": { - "status": "Confirmed", - "time": "On 29 Nov 16" - }, - "avatar": "AVATAR_IMAGE_URL", - "manager": { - "id": 17, - "firstName": "Manager", - "lastName": "User", - "jobTitle": "Head of Ops", - "email": "testuser2@email.com", - "timeZone": "New York", - "language": "en-US", - "role": "admin", - "profileUrl": "https://testaccount.learnamp.com/en/users/17", - "status": { - "status": "Confirmed", - "time": "On 20 Feb 17" - } - }, - "location": "London, UK", - "primaryTeam": { - "id": 15, - "name": "Operations", - "teamUsersCount": 10, - "apiTeamPath": "/v1/teams/15.json", - "apiTeamUsersPath": "/v1/teams/15/users.json", - "manager": { - "id": 17, - "firstName": "Manager", - "lastName": "User", - "jobTitle": "Head of Ops", - "email": "testuser2@email.com", - "timeZone": "New York", - "language": "en-US", - "role": "admin", - "profileUrl": "https://testaccount.learnamp.com/en/users/17", - "status": { - "status": "Confirmed", - "time": "On 20 Feb 17" - } - } - }, - "secondaryTeams": [] - }, - ] - } - ] -} +Remove a user from a team. -``` -``` +### HTTP Request -> 400 Bad request - validation errors: - -```json -{ - "error": "userId is missing, userId is empty", - "fullErrors": { - "userId": [ - "is missing", - "is empty" - ] - } -} -``` +`DELETE https://{API_BASE_URL}/v1/teams/{team_id}/users/{user_id}` -## Remove a User from a Team +### Required Scope +This endpoint requires the `team_users:delete` scope. + +## Add Users to a Team -> Remove a user from team: +> Add multiple users to a team: ```shell -curl --location --request DELETE 'https://api.learnamp.com/v1/teams/1/users/1' \ ---header 'Authorization: Bearer YOUR-ACCESS-TOKEN' +curl --location --request POST 'https://api.learnamp.com/v1/teams/1/bulk/users' \ +--header 'Authorization: Bearer YOUR-ACCESS-TOKEN' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "userIds": [1, 2, 3], + "isPrimary": true +}' ``` ```ruby @@ -478,8 +188,13 @@ module Learnamp @token = token end - def delete(team_id, user_id) - response = self.class.delete("/teams/#{team_id}/users/#{user_id}", { headers: headers }) + def bulk_add(team_id, users_details) + response = self.class.post("/teams/#{team_id}/bulk/users", + { + headers: headers, + body: users_details.to_json + } + ) response.parsed_response end @@ -487,30 +202,26 @@ module Learnamp def headers { - 'Authorization' => "Bearer #{token}" + 'Authorization' => "Bearer #{token}", + 'Content-Type' => 'application/json' } end end end -Learnamp::TeamUsers.new(token).delete(245, 1) -``` - -Delete a user from a team. (User and team are kept, but their association is removed). - -`DELETE https://{API_BASE_URL}/v1/teams/{teamId}/users/{userId}` - +users_details = { + userIds: [1, 2, 3], + isPrimary: true +} -> 204 No Content - successful response: +result = Learnamp::TeamUsers.new(token).bulk_add(1, users_details) +``` -```json +Add multiple users to a team in a single request. -``` +### HTTP Request -> 404 Not Found - unsuccessful response: +`POST https://{API_BASE_URL}/v1/teams/{team_id}/bulk/users` -```json -{ - "error": "Not found" -} -``` +### Required Scope +This endpoint requires the `team_users:create` scope. diff --git a/source/includes/_teams.md b/source/includes/_teams.md index 87cad27cd85..87ba72049c5 100644 --- a/source/includes/_teams.md +++ b/source/includes/_teams.md @@ -51,6 +51,9 @@ View all teams `GET https://{API_BASE_URL}/v1/teams` +### Required Scope +This endpoint requires the `teams:read` scope. + Response will be paginated [see pagination](#pagination) @@ -333,6 +336,9 @@ Create a Team `POST https://{API_BASE_URL}/v1/teams` +### Required Scope +This endpoint requires the `teams:create` scope. + ### Data in Body Parameter (* required) | Example value | Description @@ -453,6 +459,9 @@ Update a Team `PUT https://{API_BASE_URL}/v1/items` +### Required Scope +This endpoint requires the `teams:update` scope. + ### Data in Body Parameter | Example value | Description @@ -560,6 +569,8 @@ Delete a team. (Users are kept, but their association with team is removed). `DELETE https://{API_BASE_URL}/v1/teams/{teamId}` +### Required Scope +This endpoint requires the `teams:delete` scope. > 204 No Content - successful response: diff --git a/source/includes/_users.md b/source/includes/_users.md index c48a3b4654e..0ff8463a4e4 100644 --- a/source/includes/_users.md +++ b/source/includes/_users.md @@ -48,6 +48,9 @@ View all users. `GET https://{API_BASE_URL}/v1/users` +### Required Scope +This endpoint requires the `users:read` scope. + Response will be paginated [see pagination](#pagination) ### Optional Filters in URL Params @@ -208,6 +211,8 @@ Display user details for one specific user. `GET https://{API_BASE_URL}/v1/users/{userId}` +### Required Scope +This endpoint requires the `users:read` scope. > 200 OK - successful response: @@ -352,6 +357,9 @@ Create a user and trigger an invite email. `POST https://{API_BASE_URL}/v1/users` +### Required Scope +This endpoint requires the `users:create` scope. + ### Data in Body Parameter | Example value | Description (* required) @@ -522,6 +530,9 @@ Update a user's details'. `PUT https://{API_BASE_URL}/v1/users/{userId}` +### Required Scope +This endpoint requires the `users:update` scope. + ### Data in Body Parameter | type | Example value | Description (* required) @@ -660,6 +671,8 @@ Deactivate a user, so that they can no longer login. Their data is not removed. `PUT https://{API_BASE_URL}/v1/users/{userId}/deactivate` +### Required Scope +This endpoint requires the `users:deactivate` scope. > 204 No Content - successful response: @@ -718,6 +731,8 @@ Reactivate a user, so that they login again. `PUT https://{API_BASE_URL}/v1/users/{userId}/reactivate` +### Required Scope +This endpoint requires the `users:reactivate` scope. > 204 No Content - successful response: @@ -776,6 +791,8 @@ Delete a user, so that they can no longer login. Their data is removed. `DELETE https://{API_BASE_URL}/v1/users/{userId}` +### Required Scope +This endpoint requires the `users:delete` scope. > 204 No Content - successful response: @@ -834,6 +851,9 @@ View progress of all assigned channels by a specified user. This is analogous to `GET https://{API_BASE_URL}/v1/users/{userId}/channels_progress` +### Required Scope +This endpoint requires the `user_channels_progress:read` scope. + This end-point will return a paginated array of channels that are assigned to the specified user. Each element will contain the completion percentage of the channel by that user, as well as the datetime (if any) when the channel was completed. Please note: The completion percentage is a cached value, which is refreshed in the background automatically. The completion percentage shown may therefore take a few minutes to update. @@ -894,4 +914,4 @@ Response will be paginated [see pagination](#pagination) { "error": "Not found" } -``` \ No newline at end of file +``` diff --git a/source/includes/_verbs.md b/source/includes/_verbs.md index 2829ef59903..bdd1110456a 100644 --- a/source/includes/_verbs.md +++ b/source/includes/_verbs.md @@ -47,6 +47,9 @@ View all verbs `GET https://{API_BASE_URL}/v1/verbs` +### Required Scope +This endpoint requires the `verbs:read` scope. + Response will be paginated [see pagination](#pagination) @@ -147,4 +150,4 @@ Response will be paginated [see pagination](#pagination) } ] } -``` \ No newline at end of file +``` From dd7d04b419553d6b75207d93e52f6b526a23e285 Mon Sep 17 00:00:00 2001 From: Thomas Millward Wright Date: Tue, 11 Mar 2025 12:13:02 +0000 Subject: [PATCH 2/3] [LA-25920] restore removed stuff --- source/includes/_team_users.md | 174 +++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/source/includes/_team_users.md b/source/includes/_team_users.md index 55edf55bf7f..925b8f3e8af 100644 --- a/source/includes/_team_users.md +++ b/source/includes/_team_users.md @@ -114,6 +114,180 @@ Add a user to a team. ### Required Scope This endpoint requires the `team_users:create` scope. +## Add a User to a Team - Alternative Method + +> Add a user to a team by email and team name: + +```shell +curl --location --request POST 'https://api.learnamp.com/v1/teams/users' \ +--header 'Authorization: Bearer YOUR-ACCESS-TOKEN' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "teamName": "Marketing", + "userEmail": "new@member.com" +}' +``` + +```ruby +module Learnamp + class TeamUsers + include HTTParty + base_uri "#{ENV['BASE_URL']}#{ENV['API_PATH']}" + + attr_accessor :token + + def initialize(token) + @token = token + end + + def create(params) + response = self.class.post('/teams/users', { + headers: headers, + body: params.to_json + }) + response.parsed_response + end + + private + + def headers + { + 'Authorization' => "Bearer #{token}", + 'Content-Type' => 'application/json' + } + end + end +end + +params = { + userEmail: 'user@email.com', + teamName: 'Tech Team' +} + +Learnamp::TeamUsers.new(token).create(params) +``` + +Adds a user to a Team using email and team name instead of IDs. + +In order to simplify integration with third party services, another +endpoint responsible for team member creation was implemented. + +### HTTP Request + +`POST https://{API_BASE_URL}/v1/teams/users` + +### Required Scope +This endpoint requires the `team_users:create` scope. + +### Data in Body + +Parameter | Example value | Description +--------- | ------- | ----------- +teamId | 1200 | ID of the team +teamName | "Marketing" | Name of the team +userId | 1 | User ID of user to add to team +userEmail | "user@email.com" | Email of the new team member + +Parameters `teamId` and `teamName` are mutually exclusive - only one of them can be present in the request payload. Same rule applies for `userId` and `userEmail`. + +> 201 Created - successful response: + +```json +{ + "id": 1, + "name": "Test Team", + "teamUsersCount": 2, + "apiTeamPath": "/v1/teams/1.json", + "apiTeamUsersPath": "/v1/teams/1/users.json", + "manager": { + "id": 7, + "firstName": "Test", + "lastName": "Manager", + "jobTitle": "Ops Director", + "email": "admin@example.com", + "timeZone": "London", + "language": "en", + "role": "admin", + "profileUrl": "http://testaccount.learnamp.com/en/users/7", + "status": { + "status": "Invite pending", + "time": "Sent 25 Sep 19" + } + }, + "users": [ + { + "id": 1, + "firstName": "Test", + "lastName": "User", + "jobTitle": "Developer", + "email": "test@email.com", + "timeZone": "London", + "language": "en", + "role": "viewer", + "profileUrl": "https://testaccount.learnamp.com/en/users/1", + "status": { + "status": "Confirmed", + "time": "On 29 Nov 16" + }, + "avatar": "AVATAR_IMAGE_URL", + "manager": { + "id": 17, + "firstName": "Manager", + "lastName": "User", + "jobTitle": "Head of Ops", + "email": "testuser2@email.com", + "timeZone": "New York", + "language": "en-US", + "role": "admin", + "profileUrl": "https://testaccount.learnamp.com/en/users/17", + "status": { + "status": "Confirmed", + "time": "On 20 Feb 17" + } + }, + "location": "London, UK", + "primaryTeam": { + "id": 15, + "name": "Operations", + "teamUsersCount": 10, + "apiTeamPath": "/v1/teams/15.json", + "apiTeamUsersPath": "/v1/teams/15/users.json", + "manager": { + "id": 17, + "firstName": "Manager", + "lastName": "User", + "jobTitle": "Head of Ops", + "email": "testuser2@email.com", + "timeZone": "New York", + "language": "en-US", + "role": "admin", + "profileUrl": "https://testaccount.learnamp.com/en/users/17", + "status": { + "status": "Confirmed", + "time": "On 20 Feb 17" + } + } + }, + "secondaryTeams": [] + } + ] +} +``` + +> 400 Bad request - validation errors: + +```json +{ + "error": "userId is missing, userId is empty", + "fullErrors": { + "userId": [ + "is missing", + "is empty" + ] + } +} +``` + ## Remove a User from a Team > Remove a user from a team: From 57f315051bc8ed842947f5ae8a560ec81184315c Mon Sep 17 00:00:00 2001 From: Thomas Millward Wright Date: Tue, 11 Mar 2025 12:17:12 +0000 Subject: [PATCH 3/3] [LA-25920] and again --- source/includes/_team_users.md | 195 +++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) diff --git a/source/includes/_team_users.md b/source/includes/_team_users.md index 925b8f3e8af..2784658e88e 100644 --- a/source/includes/_team_users.md +++ b/source/includes/_team_users.md @@ -50,6 +50,90 @@ This endpoint requires the `team_users:read` scope. Response will be paginated [see pagination](#pagination) +> 200 OK - successful response: + +```json +{ + "id": 379, + "name": "Test Team", + "teamUsersCount": 2, + "apiTeamPath": "/v1/teams/379.json", + "apiTeamUsersPath": "/v1/teams/379/users.json", + "manager": { + "id": 7, + "firstName": "Test", + "lastName": "Manager", + "jobTitle": "Ops Director", + "email": "admin@example.com", + "timeZone": "London", + "language": "en", + "role": "admin", + "profileUrl": "http://testaccount.learnamp.com/en/users/7", + "status": { + "status": "Invite pending", + "time": "Sent 25 Sep 19" + } + }, + "users": [ + { + "id": 1, + "firstName": "Test", + "lastName": "User", + "jobTitle": "Developer", + "email": "test@email.com", + "timeZone": "London", + "language": "en", + "role": "viewer", + "profileUrl": "https://testaccount.learnamp.com/en/users/1", + "status": { + "status": "Confirmed", + "time": "On 29 Nov 16" + }, + "avatar": "AVATAR_IMAGE_URL", + "manager": { + "id": 17, + "firstName": "Manager", + "lastName": "User", + "jobTitle": "Head of Ops", + "email": "testuser2@email.com", + "timeZone": "New York", + "language": "en-US", + "role": "admin", + "profileUrl": "https://testaccount.learnamp.com/en/users/17", + "status": { + "status": "Confirmed", + "time": "On 20 Feb 17" + } + }, + "location": "London, UK", + "primaryTeam": { + "id": 15, + "name": "Operations", + "teamUsersCount": 10, + "apiTeamPath": "/v1/teams/15.json", + "apiTeamUsersPath": "/v1/teams/15/users.json", + "manager": { + "id": 17, + "firstName": "Manager", + "lastName": "User", + "jobTitle": "Head of Ops", + "email": "testuser2@email.com", + "timeZone": "New York", + "language": "en-US", + "role": "admin", + "profileUrl": "https://testaccount.learnamp.com/en/users/17", + "status": { + "status": "Confirmed", + "time": "On 20 Feb 17" + } + } + }, + "secondaryTeams": [] + } + ] +} +``` + ## Add a User to a Team > Add a user to a team: @@ -114,6 +198,104 @@ Add a user to a team. ### Required Scope This endpoint requires the `team_users:create` scope. +> 201 Created - successful response: + +```json +{ + "id": 1, + "name": "Test Team", + "teamUsersCount": 2, + "apiTeamPath": "/v1/teams/1.json", + "apiTeamUsersPath": "/v1/teams/1/users.json", + "manager": { + "id": 7, + "firstName": "Test", + "lastName": "Manager", + "jobTitle": "Ops Director", + "email": "admin@example.com", + "timeZone": "London", + "language": "en", + "role": "admin", + "profileUrl": "http://testaccount.learnamp.com/en/users/7", + "status": { + "status": "Invite pending", + "time": "Sent 25 Sep 19" + } + }, + "users": [ + { + "id": 1, + "firstName": "Test", + "lastName": "User", + "jobTitle": "Developer", + "email": "test@email.com", + "timeZone": "London", + "language": "en", + "role": "viewer", + "profileUrl": "https://testaccount.learnamp.com/en/users/1", + "status": { + "status": "Confirmed", + "time": "On 29 Nov 16" + }, + "avatar": "AVATAR_IMAGE_URL", + "manager": { + "id": 17, + "firstName": "Manager", + "lastName": "User", + "jobTitle": "Head of Ops", + "email": "testuser2@email.com", + "timeZone": "New York", + "language": "en-US", + "role": "admin", + "profileUrl": "https://testaccount.learnamp.com/en/users/17", + "status": { + "status": "Confirmed", + "time": "On 20 Feb 17" + } + }, + "location": "London, UK", + "primaryTeam": { + "id": 15, + "name": "Operations", + "teamUsersCount": 10, + "apiTeamPath": "/v1/teams/15.json", + "apiTeamUsersPath": "/v1/teams/15/users.json", + "manager": { + "id": 17, + "firstName": "Manager", + "lastName": "User", + "jobTitle": "Head of Ops", + "email": "testuser2@email.com", + "timeZone": "New York", + "language": "en-US", + "role": "admin", + "profileUrl": "https://testaccount.learnamp.com/en/users/17", + "status": { + "status": "Confirmed", + "time": "On 20 Feb 17" + } + } + }, + "secondaryTeams": [] + } + ] +} +``` + +> 400 Bad request - validation errors: + +```json +{ + "error": "userId is missing, userId is empty", + "fullErrors": { + "userId": [ + "is missing", + "is empty" + ] + } +} +``` + ## Add a User to a Team - Alternative Method > Add a user to a team by email and team name: @@ -336,6 +518,19 @@ Remove a user from a team. ### Required Scope This endpoint requires the `team_users:delete` scope. +> 204 No Content - successful response: + +```json +``` + +> 404 Not Found - unsuccessful response: + +```json +{ + "error": "Not found" +} +``` + ## Add Users to a Team > Add multiple users to a team: