RequestRocket Documentation
API ReferenceCore API

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

MethodEndpointDescription
GET/api/clientsList all clients you're a member of
POST/api/clientsCreate a new client
GET/api/clients/{clientId}Get a specific client
GET/api/clients/{clientId}/telemetryRetrieve 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

FieldTypeRequiredDescription
clientNamestringYesName of the organisation
returnUserbooleanNoIf 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

FieldTypeRequiredDescription
clientNamestringYesUpdated name for the organisation
returnUserbooleanNoIf 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

ParameterTypeRequiredDescription
intervalstringNoAggregation interval: minute, hour, day, or month (default: hour)
startDatestring (date-time)NoInclude telemetry data starting from this time (inclusive)
endDatestring (date-time)NoInclude telemetry data ending at this time (inclusive)
limitintegerNoMaximum 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.

FieldTypeDescription
pKeystringClient ID
sKeystringTimestamp key (YYYY-MM-DD-HH-MM / YYYY-MM-DD-HH / YYYY-MM-DD / YYYY-MM)
countMapRecord<source, integer>Total request count per source
successCountMapRecord<source, integer>Successful requests (2xx / 3xx) per source
errorCountMapRecord<source, integer>Error requests (4xx / 5xx) per source
totalResponseTimeMapRecord<source, float>Cumulative response time in ms per source
codeCountMapRecord<"statusCode:source", integer>Request count per HTTP status code and source
codeTotalRTMapRecord<"statusCode:source", float>Cumulative response time per status code and source
countryCountMapRecord<"countryCode:source", integer>Request count per country (ISO 3166-1 alpha-2) and source
countryTotalRTMapRecord<"countryCode:source", float>Cumulative response time per country and source
averageResponseTimeMapRecord<source, float>Average response time per source (derived)
successRateMapRecord<source, float>Success rate per source (derived)
errorRateMapRecord<source, float>Error rate per source (derived)
countryAverageRTMapRecord<"countryCode:source", float>Average response time per country and source (derived)
ewmaResponseTimefloatExponentially 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

FieldTypeRequiredDescription
immediatelyDeletebooleanNoIf 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
}

Next Steps

On this page