MSP organisation and team API
Read an MSP team and its configuration.
The handler for members lists the team and, for a system admin, can add an existing user. Invites are the normal way to add someone. Configuration holds billing type and the rates floor.
MSP roles
| Role | Proven access |
|---|---|
msp_owner | Manage clients, own-team members and invites, managed-client teams, configuration, plans, relationships, and billing. |
msp_admin | Manage the same subresources, except only an owner can grant or remove msp_owner. |
msp_user | Read clients, configuration, plans, and telemetry; manage managed-client members and invites; cannot manage the MSP's own team. |
msp_reader | Read clients, members, invites, configuration, plans, and telemetry. |
Endpoints
| Method | Path | What it does |
|---|---|---|
| GET | /api/msps/:mspId/members | List MSP team members |
| POST | /api/msps/:mspId/members | Add an existing user (system admin) |
| PUT | /api/msps/:mspId/members/:memberId | Change member roles |
| DELETE | /api/msps/:mspId/members/:memberId | Remove a member |
| GET | /api/msps/:mspId/invites | List MSP invites |
| POST | /api/msps/:mspId/invites | Create an MSP invite |
| PUT | /api/msps/:mspId/invites/:inviteId | Respond to an invite |
| DELETE | /api/msps/:mspId/invites/:inviteId | Delete an invite |
| GET | /api/msps/:mspId/configurations | Read MSP configuration |
| PUT | /api/msps/:mspId/configurations | Update MSP configuration |
| GET | /api/msps/:mspId/promocodes | List MSP grants |
| POST | /api/msps/:mspId/promocodes | Redeem an MSP code |
List MSP members
GET /api/msps/:mspId/members returns the MSP's own team and their roles.
Request
curl -X GET "https://api.requestrocket.com/api/msps/:mspId/members" \
-H "Authorization: u-your-token"import axios from "axios";
const response = await axios.request({
method: "GET",
url: "https://api.requestrocket.com/api/msps/:mspId/members",
headers: {
"Authorization": "u-your-token",
}
});
console.log(response.status, response.data);import requests
response = requests.request(
"GET",
"https://api.requestrocket.com/api/msps/:mspId/members",
headers={
"Authorization": "u-your-token",
}
)
print(response.status_code, response.json())package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
var payload io.Reader
req, _ := http.NewRequest("GET", "https://api.requestrocket.com/api/msps/:mspId/members", payload)
req.Header.Set("Authorization", "u-your-token")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode, string(body))
}import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.requestrocket.com/api/msps/:mspId/members"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.header("Authorization", "u-your-token")
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}Responses
{
"members": [
{
"userId": "0f8e6c1a-2b7d-4c3e-9a55-1d2e3f4a5b6c",
"userFirstName": "Alex",
"userLastName": "Example",
"userEmail": "alex@example.com",
"roles": [
"msp_owner"
]
}
],
"message": "Success"
}{
"message": "Member not found in MSP"
}{
"Message": "User is not authorized to access this resource with an explicit deny in an identity-based policy"
}{
"message": "method / endpoint not supported"
}Query parameters
None.
Response
| Attribute | Type | Description |
|---|---|---|
members | array | Team members. |
members[].userId | string | User id. |
members[].userFirstName | string | Given name. |
members[].userLastName | string | Family name. |
members[].userEmail | string | Email address. |
members[].roles | string[] | One or more of msp_owner, msp_admin, msp_user, msp_reader. |
message | string | Success. |
Add an existing user
POST /api/msps/:mspId/members adds a user who already has a RequestRocket account. Only a system admin can call it. Invites are the normal way to add someone.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | ✓ | Id of the user to add. |
roles | string[] | ✓ | At least one of msp_owner, msp_admin, msp_user, msp_reader. |
Returns the membership that was stored. The array contains userId and roles for that user.
Response
| Attribute | Type | Description |
|---|---|---|
members | array | The new membership. |
members[].userId | string | User id from the request. |
members[].roles | string[] | Roles from the request. |
message | string | Member added to MSP. |
A user who is already on the team returns 409.
Change member roles
PUT /api/msps/:mspId/members/:memberId replaces the roles on one team member.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
roles | string[] | ✓ | Replacement roles. At least one of msp_owner, msp_admin, msp_user, msp_reader. Only an MSP owner can grant or remove msp_owner. |
Returns the updated membership, with userId and roles.
Response
| Attribute | Type | Description |
|---|---|---|
members | array | The updated membership. |
members[].userId | string | Member id from the path. |
members[].roles | string[] | Roles after the owner guard. |
message | string | Member roles updated. |
List MSP invites
GET /api/msps/:mspId/invites returns every invite stored for the MSP.
Query parameters
None.
Response
| Attribute | Type | Description |
|---|---|---|
invites | array | Invites whose parent is this MSP. |
invites[].inviteId | string | Invite id. |
invites[].parentId | string | MSP id. |
invites[].clientName | string | MSP name shown on the invite. |
invites[].userEmail | string | Invited email address. |
invites[].roles | string[] | Roles the invite will grant. |
invites[].inviteType | string | msp when set. |
invites[].TTL | number | Expiry stored on the invite. |
message | string | Success. |
Create an MSP invite
POST /api/msps/:mspId/invites invites an email address onto the MSP team. A repeat invite for the same address updates the existing invite.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
userEmail | string | ✓ | Email address to invite. |
userName | string | Name used in the invitation email. | |
roles | string[] | ✓ | At least one of msp_owner, msp_admin, msp_user, msp_reader. Only an MSP owner can grant msp_owner. |
Returns the invite that was sent or refreshed.
Response
| Attribute | Type | Description |
|---|---|---|
invites | array | The invite. |
invites[].inviteId | string | Invite id. |
invites[].parentId | string | MSP id. |
invites[].clientName | string | MSP name. |
invites[].userEmail | string | Invited email address. |
invites[].roles | string[] | Roles on the invite. |
invites[].inviteType | string | msp. |
invites[].TTL | number | Expiry stored on the invite. |
message | string | Invite sent. |
Update an invite
PUT /api/msps/:mspId/invites/:inviteId replaces the roles on a pending invite and extends its expiry by 14 days.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
roles | string[] | ✓ | Replacement roles. At least one of msp_owner, msp_admin, msp_user, msp_reader. Only an MSP owner can grant or remove msp_owner. |
Returns the invite after the role replacement.
Response
| Attribute | Type | Description |
|---|---|---|
invites | array | The updated invite. |
invites[].inviteId | string | Invite id from the path. |
invites[].roles | string[] | Roles from the request. |
invites[].TTL | number | Unix time, in seconds, 14 days from this call. |
message | string | Invite updated. |
Read MSP configuration
GET /api/msps/:mspId/configurations returns the MSP billing type and the rates floor.
Query parameters
None.
Response
| Attribute | Type | Description |
|---|---|---|
configuration.billingType | string | stripe, marketplace, or invoice. |
configuration.billingStatus | string | active or suspended, when set. |
configuration.promotionalCodes | array or null | Applied grants. Each item has name, createdAt, and expiresAt. The redemption secret is not included. |
configuration.rates.apiSeconds | number | Floor multiplier for API seconds. |
configuration.rates.storageGB | number | Floor multiplier for storage. |
configuration.rates.aiTokens | number | Floor multiplier for AI tokens. |
configuration.rates.plan | number | Floor multiplier for the plan fee. |
message | string | Success. |
Update MSP configuration
PUT /api/msps/:mspId/configurations updates the MSP's own configuration. All fields are optional. Omit a field to leave it unchanged. Rates and billing type are applied for a system admin. Raising the rates floor re-clamps managed organisations whose stored rates sit below the new floor.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
billingType | string | stripe, marketplace, or invoice. Applied for a system admin. | |
billingStatus | string | active or suspended. Accepted by validation and left unchanged. | |
rates | object | Floor multipliers. Applied for a system admin. Sending rates requires apiSeconds, storageGB, aiTokens, and plan. Each value is clamped to the range 0.7 to 1. | |
rates.apiSeconds | number | API-seconds floor. Required when rates is sent. | |
rates.storageGB | number | Storage floor. Required when rates is sent. | |
rates.aiTokens | number | AI-token floor. Required when rates is sent. | |
rates.plan | number | Plan-fee floor. Required when rates is sent. |
promotionalCodes is not writable here. Redeem a code on POST /api/msps/:mspId/promocodes.
Returns the saved configuration. When the new floor raises one or more managed organisations, the response also includes clientsReclamped. Balances are not overwritten.
Response
| Attribute | Type | Description |
|---|---|---|
configuration | object | Saved MSP configuration. Same shape as the GET response. |
clientsReclamped | number | How many managed organisations were raised to the new floor. Present only when that count is greater than zero. |
message | string | Configuration updated successfully. |
List MSP grants
GET /api/msps/:mspId/promocodes returns grants applied to the MSP. The redemption secret is not included.
Query parameters
None.
Response
| Attribute | Type | Description |
|---|---|---|
promotionalCodes | array or null | Applied grants. |
promotionalCodes[].name | string | Public grant name. |
promotionalCodes[].createdAt | string | ISO-8601 time the grant was applied. |
promotionalCodes[].expiresAt | string | ISO-8601 expiry. |
message | string | Success. |
Redeem an MSP code
POST /api/msps/:mspId/promocodes redeems a promotional code for the MSP.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
code | string | ✓ | Redemption secret. It is not returned. |
Returns the grant name that matched, whether it was already on the MSP, and the full grant list.
Response
| Attribute | Type | Description |
|---|---|---|
applied.name | string | Public name of the grant. |
applied.createdAt | string | ISO-8601 time the grant was applied. |
applied.expiresAt | string | ISO-8601 expiry. |
alreadyApplied | boolean | true when this grant name was already stored. |
promotionalCodes | array | Grants after this call. The secret is omitted. |
message | string | Promotional code applied, or Promotional code already applied. |
Shared status codes, the 5.5 MB cap, and plan rate limits are on Platform limits.