Members & Invites
Manage your MSP team members and send invitations to new members
Members & Invites
Manage the members of your MSP team and send invitations to onboard new members.
To add a new user to your MSP team, use the Invites endpoints to send an email invitation. The user accepts the invite from their account and is automatically added with the specified roles.
Member Endpoints
| Method | Endpoint | Description | Min Role |
|---|---|---|---|
| GET | /api/msps/{mspId}/members | List all MSP team members | msp_reader |
| GET | /api/msps/{mspId}/members/{userId} | Get a specific team member | msp_reader |
| PUT | /api/msps/{mspId}/members/{userId} | Update a member's roles | msp_admin |
| DELETE | /api/msps/{mspId}/members/{userId} | Remove a member from the MSP | msp_admin |
Invite Endpoints
| Method | Endpoint | Description | Min Role |
|---|---|---|---|
| GET | /api/msps/{mspId}/invites | List all pending invites | msp_admin |
| POST | /api/msps/{mspId}/invites | Send a new invitation | msp_admin |
| PUT | /api/msps/{mspId}/invites/{inviteId} | Update roles or re-issue an invite | msp_admin |
| DELETE | /api/msps/{mspId}/invites/{inviteId} | Cancel a pending invite | msp_admin |
List Members
Retrieve all members of your MSP team.
Request
GET /api/msps/{mspId}/members HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}Response
{
"members": [
{
"userId": "123e4567-e89b-12d3-a456-426614174000",
"roles": ["msp_owner"],
"userEmail": "alice@example.com",
"userFirstName": "Alice",
"userLastName": "Smith",
"userCreated": "2024-01-10T08:00:00.000Z",
"userUpdated": "2024-01-20T10:30:00.000Z"
},
{
"userId": "223e4567-e89b-12d3-a456-426614174001",
"roles": ["msp_admin"],
"userEmail": "bob@example.com",
"userFirstName": "Bob",
"userLastName": "Johnson",
"userCreated": "2024-02-01T09:00:00.000Z",
"userUpdated": "2024-02-10T11:20:00.000Z"
}
],
"message": "Success"
}Example
curl -X GET "https://api.requestrocket.com/api/msps/${MSP_ID}/members" \
-H "Authorization: ${USER_TOKEN}"const response = await fetch(
`https://api.requestrocket.com/api/msps/${mspId}/members`,
{
headers: { 'Authorization': process.env.USER_TOKEN }
}
);
const data = await response.json();
console.log('Team members:', data.members);import requests, os
response = requests.get(
f'https://api.requestrocket.com/api/msps/{msp_id}/members',
headers={'Authorization': os.getenv('USER_TOKEN')}
)
print(response.json()['members'])req, _ := http.NewRequest("GET",
fmt.Sprintf("https://api.requestrocket.com/api/msps/%s/members", mspId), nil)
req.Header.Set("Authorization", os.Getenv("USER_TOKEN"))
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.requestrocket.com/api/msps/" + mspId + "/members"))
.header("Authorization", System.getenv("USER_TOKEN"))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Update Member Roles
Change the roles assigned to a team member.
- The last
msp_ownercannot have their owner role removed - The last
msp_admincannot have their admin role removed - Both protections apply to the member being edited, not the requestor
Request
PUT /api/msps/{mspId}/members/{userId} HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}
Content-Type: application/json
{
"roles": ["msp_admin"]
}Request Body
| Field | Type | Required | Description |
|---|---|---|---|
roles | string[] | Yes | One or more roles to assign. Valid values: msp_owner, msp_admin, msp_user, msp_reader |
Response
{
"members": [
{
"userId": "223e4567-e89b-12d3-a456-426614174001",
"roles": ["msp_admin"]
}
],
"message": "Member roles updated"
}Example
curl -X PUT "https://api.requestrocket.com/api/msps/${MSP_ID}/members/${USER_ID}" \
-H "Authorization: ${USER_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"roles": ["msp_admin"]}'const response = await fetch(
`https://api.requestrocket.com/api/msps/${mspId}/members/${userId}`,
{
method: 'PUT',
headers: {
'Authorization': process.env.USER_TOKEN,
'Content-Type': 'application/json'
},
body: JSON.stringify({ roles: ['msp_admin'] })
}
);
const data = await response.json();
console.log('Updated roles:', data.members[0].roles);import requests, os
response = requests.put(
f'https://api.requestrocket.com/api/msps/{msp_id}/members/{user_id}',
headers={'Authorization': os.getenv('USER_TOKEN')},
json={'roles': ['msp_admin']}
)
print(response.json())body := bytes.NewBufferString(`{"roles":["msp_admin"]}`)
req, _ := http.NewRequest("PUT",
fmt.Sprintf("https://api.requestrocket.com/api/msps/%s/members/%s", mspId, userId), body)
req.Header.Set("Authorization", os.Getenv("USER_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()String json = "{\"roles\": [\"msp_admin\"]}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.requestrocket.com/api/msps/" + mspId + "/members/" + userId))
.header("Authorization", System.getenv("USER_TOKEN"))
.header("Content-Type", "application/json")
.PUT(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());Remove Member
Remove a user from your MSP team. Their userMsps list is updated automatically.
You cannot remove the last msp_owner or the last msp_admin.
Request
DELETE /api/msps/{mspId}/members/{userId} HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}Response
{
"message": "Member removed from MSP"
}Example
curl -X DELETE "https://api.requestrocket.com/api/msps/${MSP_ID}/members/${USER_ID}" \
-H "Authorization: ${USER_TOKEN}"const response = await fetch(
`https://api.requestrocket.com/api/msps/${mspId}/members/${userId}`,
{ method: 'DELETE', headers: { 'Authorization': process.env.USER_TOKEN } }
);
const data = await response.json();
console.log(data.message);import requests, os
response = requests.delete(
f'https://api.requestrocket.com/api/msps/{msp_id}/members/{user_id}',
headers={'Authorization': os.getenv('USER_TOKEN')}
)
print(response.json()['message'])req, _ := http.NewRequest("DELETE",
fmt.Sprintf("https://api.requestrocket.com/api/msps/%s/members/%s", mspId, userId), nil)
req.Header.Set("Authorization", os.Getenv("USER_TOKEN"))
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.requestrocket.com/api/msps/" + mspId + "/members/" + userId))
.header("Authorization", System.getenv("USER_TOKEN"))
.DELETE()
.build();
HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());Send Invite
Invite a new user to join your MSP team by email. If the email matches an existing RequestRocket account, the invite is linked to that user. If no account exists, the user can sign up and then accept the invite.
Request
POST /api/msps/{mspId}/invites HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}
Content-Type: application/json
{
"userEmail": "newmember@example.com",
"roles": ["msp_user"]
}Request Body
| Field | Type | Required | Description |
|---|---|---|---|
userEmail | string | Yes | Email address of the person to invite |
roles | string[] | Yes | Roles to assign on acceptance. Valid values: msp_owner, msp_admin, msp_user, msp_reader |
Response
{
"invites": [
{
"inviteId": "abc12345-e89b-12d3-a456-426614174000",
"userEmail": "newmember@example.com",
"roles": ["msp_user"],
"inviteExpiry": "2024-03-01T00:00:00.000Z",
"inviteCreated": "2024-02-15T10:00:00.000Z"
}
],
"message": "Invite created"
}Example
curl -X POST "https://api.requestrocket.com/api/msps/${MSP_ID}/invites" \
-H "Authorization: ${USER_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"userEmail": "newmember@example.com",
"roles": ["msp_user"]
}'const response = await fetch(
`https://api.requestrocket.com/api/msps/${mspId}/invites`,
{
method: 'POST',
headers: {
'Authorization': process.env.USER_TOKEN,
'Content-Type': 'application/json'
},
body: JSON.stringify({
userEmail: 'newmember@example.com',
roles: ['msp_user']
})
}
);
const data = await response.json();
console.log('Invite created:', data.invites[0].inviteId);import requests, os
response = requests.post(
f'https://api.requestrocket.com/api/msps/{msp_id}/invites',
headers={'Authorization': os.getenv('USER_TOKEN')},
json={'userEmail': 'newmember@example.com', 'roles': ['msp_user']}
)
print(response.json())body := bytes.NewBufferString(`{"userEmail":"newmember@example.com","roles":["msp_user"]}`)
req, _ := http.NewRequest("POST",
fmt.Sprintf("https://api.requestrocket.com/api/msps/%s/invites", mspId), body)
req.Header.Set("Authorization", os.Getenv("USER_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()String json = "{\"userEmail\":\"newmember@example.com\",\"roles\":[\"msp_user\"]}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.requestrocket.com/api/msps/" + mspId + "/invites"))
.header("Authorization", System.getenv("USER_TOKEN"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());Update Invite
Update the roles on a pending invite and extend its expiry by 14 days, effectively re-issuing it.
Request
PUT /api/msps/{mspId}/invites/{inviteId} HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}
Content-Type: application/json
{
"roles": ["msp_admin"]
}Request Body
| Field | Type | Required | Description |
|---|---|---|---|
roles | string[] | Yes | Updated roles to assign on acceptance |
Response
{
"invites": [
{
"inviteId": "abc12345-e89b-12d3-a456-426614174000",
"userEmail": "newmember@example.com",
"roles": ["msp_admin"],
"inviteExpiry": "2024-03-15T00:00:00.000Z",
"inviteUpdated": "2024-03-01T10:00:00.000Z"
}
],
"message": "Invite updated"
}Cancel Invite
Revoke a pending invite. The invitation link will no longer be valid.
Request
DELETE /api/msps/{mspId}/invites/{inviteId} HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}Response
{
"message": "Invite deleted"
}Example
curl -X DELETE "https://api.requestrocket.com/api/msps/${MSP_ID}/invites/${INVITE_ID}" \
-H "Authorization: ${USER_TOKEN}"const response = await fetch(
`https://api.requestrocket.com/api/msps/${mspId}/invites/${inviteId}`,
{ method: 'DELETE', headers: { 'Authorization': process.env.USER_TOKEN } }
);
const data = await response.json();
console.log(data.message);import requests, os
response = requests.delete(
f'https://api.requestrocket.com/api/msps/{msp_id}/invites/{invite_id}',
headers={'Authorization': os.getenv('USER_TOKEN')}
)
print(response.json()['message'])req, _ := http.NewRequest("DELETE",
fmt.Sprintf("https://api.requestrocket.com/api/msps/%s/invites/%s", mspId, inviteId), nil)
req.Header.Set("Authorization", os.Getenv("USER_TOKEN"))
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.requestrocket.com/api/msps/" + mspId + "/invites/" + inviteId))
.header("Authorization", System.getenv("USER_TOKEN"))
.DELETE()
.build();
HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());Error Responses
| Status | Message | Cause |
|---|---|---|
| 400 | Roles required | No roles provided in the request body |
| 400 | Input failed data validation | Invalid role value or malformed body |
| 404 | Member not found in MSP | The userId is not a member of this MSP |
| 400 | Cannot remove last msp_owner | Removing the sole owner is not permitted |
| 400 | Cannot remove last msp_admin | Removing the sole admin is not permitted |
| 409 | Invite already exists for this email | A pending invite for this email already exists — use PUT to re-issue |