Clients API
Manage organisations (clients) programmatically
Clients API
Manage organisations (referred to as "clients" in the API) programmatically. Clients are the top-level entity in RequestRocket that contain users, credentials, targets, and proxies.
In the RequestRocket UI, clients are called "organisations". The API uses the term "clients" for historical reasons.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/clients | List all clients you're a member of |
| POST | /api/clients | Create a new client |
| GET | /api/clients/{clientId} | Get a specific client |
| GET | /api/clients/{clientId}/telemetry | Retrieve aggregated telemetry for a client |
| PUT | /api/clients/{clientId} | Update a client |
| DELETE | /api/clients/{clientId} | Delete a client |
List Clients
Get all clients (organisations) of which you are a member.
Request
GET /api/clients HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}Response
{
"clients": [
{
"clientId": "550e8400-e29b-41d4-a716-446655440000",
"clientName": "My Organisation",
"clientMembers": [
{
"userId": "123e4567-e89b-12d3-a456-426614174000",
"roles": ["owner", "admin"]
}
],
}
],
"message": "Success"
}Example
const response = await fetch('https://api.requestrocket.com/api/clients', {
headers: {
'Authorization': process.env.USER_TOKEN
}
});
const data = await response.json();
console.log('Your organisations:', data.clients);import requests
import os
response = requests.get(
'https://api.requestrocket.com/api/clients',
headers={'Authorization': os.getenv('USER_TOKEN')}
)
data = response.json()
print(f"Found {len(data['clients'])} organisations")package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
type Response struct {
Clients []map[string]interface{} `json:"clients"`
Message string `json:"message"`
}
func main() {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://api.requestrocket.com/api/clients", nil)
req.Header.Set("Authorization", os.Getenv("USER_TOKEN"))
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var result Response
json.Unmarshal(body, &result)
fmt.Printf("Found %d organisations\n", len(result.Clients))
}import java.net.http.*;
import java.net.URI;
import com.google.gson.*;
public class ListClients {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.requestrocket.com/api/clients"))
.header("Authorization", System.getenv("USER_TOKEN"))
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
JsonArray clients = json.getAsJsonArray("clients");
System.out.println("Found " + clients.size() + " organisations");
}
}curl -X GET "https://api.requestrocket.com/api/clients" \
-H "Authorization: ${USER_TOKEN}"Create Client
Create a new client (organisation). This automatically creates a Stripe customer and adds you as the owner and admin.
Request
POST /api/clients HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}
Content-Type: application/json
{
"clientName": "New Organisation",
"returnUser": false
}Request Body
| Field | Type | Required | Description |
|---|---|---|---|
clientName | string | Yes | Name of the organisation |
returnUser | boolean | No | If true, includes the updated user object in the response |
Response
{
"clients": [
{
"clientId": "650e8400-e29b-41d4-a716-446655440001",
"clientName": "New Organisation",
"clientMembers": [
{
"userId": "123e4567-e89b-12d3-a456-426614174000",
"roles": ["owner", "admin"]
}
],
}
],
"message": "client created successfully"
}The system automatically provisions a Stripe customer for billing purposes when you create a new client.
Example
const response = await fetch('https://api.requestrocket.com/api/clients', {
method: 'POST',
headers: {
'Authorization': process.env.USER_TOKEN,
'Content-Type': 'application/json'
},
body: JSON.stringify({
clientName: 'New Organisation'
})
});
const data = await response.json();
console.log('Created client:', data.clients[0].clientId);import requests
import os
response = requests.post(
'https://api.requestrocket.com/api/clients',
headers={'Authorization': os.getenv('USER_TOKEN')},
json={'clientName': 'New Organisation'}
)
data = response.json()
print(f"Created client: {data['clients'][0]['clientId']}")package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
type CreateClientRequest struct {
ClientName string `json:"clientName"`
}
type Response struct {
Clients []map[string]interface{} `json:"clients"`
Message string `json:"message"`
}
func main() {
requestBody, _ := json.Marshal(CreateClientRequest{
ClientName: "New Organisation",
})
req, _ := http.NewRequest("POST", "https://api.requestrocket.com/api/clients",
bytes.NewBuffer(requestBody))
req.Header.Set("Authorization", os.Getenv("USER_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var result Response
json.Unmarshal(body, &result)
fmt.Printf("Created client: %v\n", result.Clients[0]["clientId"])
}import java.net.http.*;
import java.net.URI;
import com.google.gson.*;
public class CreateClient {
public static void main(String[] args) throws Exception {
String json = "{\"clientName\": \"New Organisation\"}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.requestrocket.com/api/clients"))
.header("Authorization", System.getenv("USER_TOKEN"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
JsonObject jsonResponse = JsonParser.parseString(response.body()).getAsJsonObject();
JsonArray clients = jsonResponse.getAsJsonArray("clients");
JsonObject newClient = clients.get(0).getAsJsonObject();
System.out.println("Created client: " + newClient.get("clientId").getAsString());
}
}curl -X POST "https://api.requestrocket.com/api/clients" \
-H "Authorization: ${USER_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"clientName": "New Organisation"
}'Get Client
Retrieve details of a specific client.
Request
GET /api/clients/{clientId} HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}Response
{
"clients": [
{
"clientId": "550e8400-e29b-41d4-a716-446655440000",
"clientName": "My Organisation",
"clientMembers": [
{
"userId": "123e4567-e89b-12d3-a456-426614174000",
"roles": ["owner", "admin"]
}
],
}
],
"message": "Success"
}Example
const response = await fetch(
`https://api.requestrocket.com/api/clients/${clientId}`,
{
headers: {
'Authorization': process.env.USER_TOKEN
}
}
);
const data = await response.json();
console.log('Client:', data.clients[0]);import requests
import os
client_id = "your-client-id"
response = requests.get(
f'https://api.requestrocket.com/api/clients/{client_id}',
headers={'Authorization': os.getenv('USER_TOKEN')}
)
data = response.json()
print(f"Client: {data['clients'][0]['clientName']}")package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
type Response struct {
Clients []map[string]interface{} `json:"clients"`
Message string `json:"message"`
}
func main() {
clientId := "your-client-id"
url := fmt.Sprintf("https://api.requestrocket.com/api/clients/%s", clientId)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", os.Getenv("USER_TOKEN"))
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var result Response
json.Unmarshal(body, &result)
fmt.Printf("Client: %v\n", result.Clients[0])
}import java.net.http.*;
import java.net.URI;
import com.google.gson.*;
public class GetClient {
public static void main(String[] args) throws Exception {
String clientId = "your-client-id";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.requestrocket.com/api/clients/" + clientId))
.header("Authorization", System.getenv("USER_TOKEN"))
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
JsonArray clients = json.getAsJsonArray("clients");
System.out.println("Client: " + clients.get(0));
}
}curl -X GET "https://api.requestrocket.com/api/clients/${CLIENT_ID}" \
-H "Authorization: ${USER_TOKEN}"Update Client
Update an existing client's information. Only the client name can be modified through this endpoint.
Request
PUT /api/clients/{clientId} HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}
Content-Type: application/json
{
"clientName": "Updated Organisation Name",
"returnUser": false
}Request Body
| Field | Type | Required | Description |
|---|---|---|---|
clientName | string | Yes | Updated name for the organisation |
returnUser | boolean | No | If true, includes the updated user object in the response |
Client members and roles are managed through the Members API. Stripe-related fields are managed automatically or through the Stripe portal.
Response
{
"clients": [
{
"clientId": "550e8400-e29b-41d4-a716-446655440000",
"clientName": "Updated Organisation Name",
"clientMembers": [
{
"userId": "123e4567-e89b-12d3-a456-426614174000",
"roles": ["owner", "admin"]
}
],
}
],
"message": "client updeated successfully"
}Example
const response = await fetch(
`https://api.requestrocket.com/api/clients/${clientId}`,
{
method: 'PUT',
headers: {
'Authorization': process.env.USER_TOKEN,
'Content-Type': 'application/json'
},
body: JSON.stringify({
clientName: 'Updated Organisation Name'
})
}
);
const data = await response.json();
console.log('Updated client:', data.clients[0]);import requests
import os
client_id = "your-client-id"
response = requests.put(
f'https://api.requestrocket.com/api/clients/{client_id}',
headers={'Authorization': os.getenv('USER_TOKEN')},
json={'clientName': 'Updated Organisation Name'}
)
data = response.json()
print(f"Updated: {data['message']}")package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
type UpdateClientRequest struct {
ClientName string `json:"clientName"`
}
func main() {
clientId := "your-client-id"
requestBody, _ := json.Marshal(UpdateClientRequest{
ClientName: "Updated Organisation Name",
})
url := fmt.Sprintf("https://api.requestrocket.com/api/clients/%s", clientId)
req, _ := http.NewRequest("PUT", url, bytes.NewBuffer(requestBody))
req.Header.Set("Authorization", os.Getenv("USER_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}import java.net.http.*;
import java.net.URI;
import com.google.gson.*;
public class UpdateClient {
public static void main(String[] args) throws Exception {
String clientId = "your-client-id";
String json = "{\"clientName\": \"Updated Organisation Name\"}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.requestrocket.com/api/clients/" + clientId))
.header("Authorization", System.getenv("USER_TOKEN"))
.header("Content-Type", "application/json")
.PUT(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}curl -X PUT "https://api.requestrocket.com/api/clients/${CLIENT_ID}" \
-H "Authorization: ${USER_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"clientName": "Updated Organisation Name"
}'Client Telemetry
Retrieve aggregated telemetry for all proxy traffic owned by a client. Results can be grouped by minute, hour, day, or month and filtered by date range.
Each telemetry record contains separate metrics for the proxy leg (RequestRocket receiving the inbound request) and the target leg (RequestRocket forwarding to the upstream API), allowing you to distinguish latency and error rates at each hop.
Request
GET /api/clients/{clientId}/telemetry?interval=hour&startDate=2025-09-01T00:00:00Z&endDate=2025-09-30T23:59:59Z&limit=100 HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
interval | string | No | Aggregation interval: minute, hour, day, or month (default: hour) |
startDate | string (date-time) | No | Include telemetry data starting from this time (inclusive) |
endDate | string (date-time) | No | Include telemetry data ending at this time (inclusive) |
limit | integer | No | Maximum number of telemetry records to return (default: 100, max: 1000) |
Response Fields
All counter and timing fields are returned as source-keyed maps with "proxy" and "target" keys. Derived maps (rates and averages) are computed by the API on read and are never stored in the database.
| Field | Type | Description |
|---|---|---|
pKey | string | Client ID |
sKey | string | Timestamp key (YYYY-MM-DD-HH-MM / YYYY-MM-DD-HH / YYYY-MM-DD / YYYY-MM) |
countMap | Record<source, integer> | Total request count per source |
successCountMap | Record<source, integer> | Successful requests (2xx / 3xx) per source |
errorCountMap | Record<source, integer> | Error requests (4xx / 5xx) per source |
totalResponseTimeMap | Record<source, float> | Cumulative response time in ms per source |
codeCountMap | Record<"statusCode:source", integer> | Request count per HTTP status code and source |
codeTotalRTMap | Record<"statusCode:source", float> | Cumulative response time per status code and source |
countryCountMap | Record<"countryCode:source", integer> | Request count per country (ISO 3166-1 alpha-2) and source |
countryTotalRTMap | Record<"countryCode:source", float> | Cumulative response time per country and source |
averageResponseTimeMap | Record<source, float> | Average response time per source (derived) |
successRateMap | Record<source, float> | Success rate per source (derived) |
errorRateMap | Record<source, float> | Error rate per source (derived) |
countryAverageRTMap | Record<"countryCode:source", float> | Average response time per country and source (derived) |
ewmaResponseTime | float | Exponentially weighted moving average of response time |
Response
{
"message": "Success",
"interval": "hour",
"telemetry": [
{
"pKey": "6330abfe-3d15-4ca1-ac2d-e435138c74ca",
"sKey": "2025-09-10-02",
"countMap": { "proxy": 150, "target": 142 },
"successCountMap": { "proxy": 148, "target": 140 },
"errorCountMap": { "proxy": 2, "target": 2 },
"totalResponseTimeMap":{ "proxy": 116.145, "target": 110.036 },
"codeCountMap": {
"200:proxy": 148, "200:target": 140,
"429:proxy": 2, "429:target": 2
},
"codeTotalRTMap": {
"200:proxy": 113.822, "200:target": 107.713,
"429:proxy": 2.323, "429:target": 2.323
},
"countryCountMap": {
"US:proxy": 90, "US:target": 85,
"AU:proxy": 60, "AU:target": 57
},
"countryTotalRTMap": {
"US:proxy": 69.687, "US:target": 65.834,
"AU:proxy": 46.458, "AU:target": 44.202
},
"averageResponseTimeMap": { "proxy": 0.7743, "target": 0.7749 },
"successRateMap": { "proxy": 0.9867, "target": 0.9859 },
"errorRateMap": { "proxy": 0.0133, "target": 0.0141 },
"countryAverageRTMap": {
"US:proxy": 0.7743, "US:target": 0.7745,
"AU:proxy": 0.7743, "AU:target": 0.7754
},
"ewmaResponseTime": 0.7681
}
]
}Delete Client
Delete a client and all associated resources. Only the sole remaining admin / owner can delete a client.
Deleting a client will permanently delete all associated credentials, targets, proxies, rules, and request history. This action cannot be undone!
Deleting a client does not delete any records we require for billing or legal purposes.
Request
DELETE /api/clients/{clientId} HTTP/1.1
Host: api.requestrocket.com
Authorization: {user_token}
Content-Type: application/json
{
"immediatelyDelete": false
}Request Body
| Field | Type | Required | Description |
|---|---|---|---|
immediatelyDelete | boolean | No | If true, deletes immediately. If false (default), marks for deletion |
Response
{
"message": "Success"
}Example
const response = await fetch(
`https://api.requestrocket.com/api/clients/${clientId}`,
{
method: 'DELETE',
headers: {
'Authorization': process.env.USER_TOKEN,
'Content-Type': 'application/json'
},
body: JSON.stringify({
immediatelyDelete: false
})
}
);
const data = await response.json();
console.log(data.message);import requests
import os
client_id = "your-client-id"
response = requests.delete(
f'https://api.requestrocket.com/api/clients/{client_id}',
headers={'Authorization': os.getenv('USER_TOKEN')},
json={'immediatelyDelete': False}
)
data = response.json()
print(data['message'])package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
type Response struct {
Message string `json:"message"`
}
func main() {
clientId := "your-client-id"
requestBody, _ := json.Marshal(map[string]bool{
"immediatelyDelete": false,
})
url := fmt.Sprintf("https://api.requestrocket.com/api/clients/%s", clientId)
req, _ := http.NewRequest("DELETE", url, bytes.NewBuffer(requestBody))
req.Header.Set("Authorization", os.Getenv("USER_TOKEN"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var result Response
json.Unmarshal(body, &result)
fmt.Println(result.Message)
}import java.net.http.*;
import java.net.URI;
import com.google.gson.*;
public class DeleteClient {
public static void main(String[] args) throws Exception {
String clientId = "your-client-id";
String json = "{\"immediatelyDelete\": false}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.requestrocket.com/api/clients/" + clientId))
.header("Authorization", System.getenv("USER_TOKEN"))
.header("Content-Type", "application/json")
.method("DELETE", HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
JsonObject jsonResponse = JsonParser.parseString(response.body()).getAsJsonObject();
System.out.println(jsonResponse.get("message").getAsString());
}
}curl -X DELETE "https://api.requestrocket.com/api/clients/${CLIENT_ID}" \
-H "Authorization: ${USER_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"immediatelyDelete": false
}'Error Responses
403 Forbidden - Not Sole Admin
If there are other admins on the client, you cannot delete it. You must first remove yourself as a member:
{
"message": "Cannot delete client - you are not the sole admin. Remove yourself from the organization via /api/clients/{clientId}/members/{userId} instead."
}Error Responses
400 Bad Request
{
"error": "Invalid client name",
"message": "Client name must be between 1 and 100 characters",
"status": 400
}404 Not Found
{
"error": "Client not found",
"message": "No client found with the specified ID",
"status": 404
}403 Forbidden
{
"error": "Insufficient permissions",
"message": "You don't have permission to access this client",
"status": 403
}