RequestRocketRequestRocketDocs
Developers

Integrating RequestRocket into Your SaaS

Learn how to use RequestRocket to power integrations in your SaaS application

Learn how to use RequestRocket as the integration layer between your SaaS application and third-party platforms.

Contents

Review the Security checklist before production use. For plan and usage information, see Plans and billing.

Integration Patterns

Choose whether your SaaS owns every integration, gives customers direct proxy access, or isolates customers in separate RequestRocket organisations.

Pattern 1: Managed Integrations

Your SaaS manages all integrations for customers, storing their third-party credentials securely.

Use Cases:

  • Pre-built connectors
  • Managed data sync

Pattern 2: Customer Self-Service

Customers use API keys you provide to make their own requests through RequestRocket.

Use Cases:

  • Developer platforms
  • API-as-a-Service
  • White-label solutions

Pattern 3: Multi-Tenant Isolation

Create separate RequestRocket clients for each of your customers.

Use Cases:

  • Enterprise customers
  • Compliance requirements
  • A separate RequestRocket organisation for each customer

Implementation Guide

This section creates an organisation, provisions the records for one customer integration, calls the resulting proxy, and optionally exposes that proxy through your application.

Set Up Your RequestRocket Infrastructure

Create your main SaaS client:

# Create your main SaaS client
curl -X POST "https://api.requestrocket.com/api/clients" \
  -H "Authorization: $RR_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clientName": "MySaaS Integration Manager"
  }'

# 201
# {
#   "clients": [
#     {
#       "clientId": "b3a1c7d2-5e44-4f0a-9c1e-7d2f8a6b1c90",
#       "clientName": "MySaaS Integration Manager",
#       "clientMembers": [
#         { "userId": "0f8e6c1a-2b7d-4c3e-9a55-1d2e3f4a5b6c", "roles": ["owner", "admin"] }
#       ]
#     }
#   ],
#   "message": "client created successfully"
# }
// Initialize your SaaS's RequestRocket client
const RR_USER_TOKEN = process.env.RR_USER_TOKEN;

async function initializeSaaS() {
  // Create your main client
  const response = await fetch('https://api.requestrocket.com/api/clients', {
    method: 'POST',
    headers: {
      'Authorization': RR_USER_TOKEN,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      clientName: 'MySaaS Integration Manager'
    })
  });
  
  const client = await response.json();
  console.log('SaaS Client ID:', client.clients[0].clientId);
  
  return client;
}
import requests
import os

RR_USER_TOKEN = os.getenv('RR_USER_TOKEN')

def initialize_saas():
    """Initialize your SaaS's RequestRocket client"""
    response = requests.post(
        'https://api.requestrocket.com/api/clients',
        headers={
            'Authorization': RR_USER_TOKEN,
            'Content-Type': 'application/json'
        },
        json={
            'clientName': 'MySaaS Integration Manager'
        }
    )
    
    client = response.json()
    print(f'SaaS Client ID: {client["clients"][0]["clientId"]}')
    
    return client
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
)

type Client struct {
    Clients []struct {
        ClientID   string `json:"clientId"`
        ClientName string `json:"clientName"`
    } `json:"clients"`
    Message string `json:"message"`
}

func initializeSaaS() (*Client, error) {
    rrToken := os.Getenv("RR_USER_TOKEN")
    
    payload := map[string]string{
        "clientName": "MySaaS Integration Manager",
    }
    
    jsonData, err := json.Marshal(payload)
    if err != nil {
        return nil, err
    }
    
    req, err := http.NewRequest(
        "POST",
        "https://api.requestrocket.com/api/clients",
        bytes.NewBuffer(jsonData),
    )
    if err != nil {
        return nil, err
    }
    
    req.Header.Set("Authorization", rrToken)
    req.Header.Set("Content-Type", "application/json")
    
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    
    body, err := io.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    
    var result Client
    if err := json.Unmarshal(body, &result); err != nil {
        return nil, err
    }
    
    fmt.Printf("SaaS Client ID: %s\n", result.Clients[0].ClientID)
    return &result, nil
}
import okhttp3.*;
import com.google.gson.Gson;
import java.io.IOException;

public class SaaSInitializer {
    private static final String RR_USER_TOKEN = System.getenv("RR_USER_TOKEN");
    private static final OkHttpClient httpClient = new OkHttpClient();
    private static final Gson gson = new Gson();
    
    public static class ClientRecord {
        public String clientId;
        public String clientName;
    }

    public static class Client {
        public ClientRecord[] clients;
        public String message;
    }
    
    public static Client initializeSaaS() throws IOException {
        // Create request payload
        String json = gson.toJson(new Object() {
            final String clientName = "MySaaS Integration Manager";
        });
        
        RequestBody body = RequestBody.create(
            json,
            MediaType.parse("application/json")
        );
        
        Request request = new Request.Builder()
            .url("https://api.requestrocket.com/api/clients")
            .header("Authorization", RR_USER_TOKEN)
            .header("Content-Type", "application/json")
            .post(body)
            .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Request failed: " + response);
            }
            
            Client client = gson.fromJson(
                response.body().string(),
                Client.class
            );
            
            System.out.println("SaaS Client ID: " + client.clients[0].clientId);
            return client;
        }
    }
}

Create Integration for a New Customer

When a customer connects a third-party service:

# 1. Create proxy credential for your customer
curl -X POST "https://api.requestrocket.com/api/clients/$SAAS_CLIENT_ID/credentials" \
  -H "Authorization: $RR_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "credentialName": "customer123-proxy-salesforce",
    "credentialType": "proxy",
    "credentialAuthType": "key",
    "credentialRegion": "us-east-2",
    "credentialSecret": {
      "key": "Authorization",
      "value": "generated-secure-key",
      "addToHeader": true
    }
  }'

# 2. Create target credential (customer's third-party creds)
curl -X POST "https://api.requestrocket.com/api/clients/$SAAS_CLIENT_ID/credentials" \
  -H "Authorization: $RR_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "credentialName": "customer123-salesforce-target",
    "credentialType": "target",
    "credentialAuthType": "none",
    "credentialRegion": "us-east-2",
    "credentialSecret": {}
  }'

# 3. Get or create target
curl -X GET "https://api.requestrocket.com/api/clients/$SAAS_CLIENT_ID/targets" \
  -H "Authorization: $RR_USER_TOKEN"

# 4. Create proxy. The response is { "proxies": [ ... ], "message": "Success" }.
# Call it at https://us-east-2.requestrocket.com/api/{proxyId}/{target-path}
curl -X POST "https://api.requestrocket.com/api/clients/$SAAS_CLIENT_ID/proxies" \
  -H "Authorization: $RR_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "proxyName": "customer123-salesforce",
    "proxyRegion": "us-east-2",
    "proxyProxyCredentialId": "inbound-credential-id",
    "proxyTargetId": "target-id",
    "proxyTargetCredentialId": "target-credential-id",
    "proxyActive": true
  }'

# Store the returned proxy details in your database
async function createCustomerIntegration(customerId, integration) {
  const { platform, credentials } = integration;
  const customerKey = generateSecureKey();
  
  // 1. Create proxy credential for your customer
  const proxyCred = await fetch(
    `https://api.requestrocket.com/api/clients/${SAAS_CLIENT_ID}/credentials`,
    {
      method: 'POST',
      headers: {
        'Authorization': RR_USER_TOKEN,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        credentialName: `${customerId}-proxy-${platform}`,
        credentialType: 'proxy',
        credentialAuthType: 'key',
        credentialRegion: 'us-east-2',
        credentialSecret: {
          key: 'Authorization',
          value: customerKey,
          addToHeader: true
        }
      })
    }
  ).then(r => r.json());
  
  // 2. Create target credential (customer's third-party creds)
  const targetCred = await fetch(
    `https://api.requestrocket.com/api/clients/${SAAS_CLIENT_ID}/credentials`,
    {
      method: 'POST',
      headers: {
        'Authorization': RR_USER_TOKEN,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        credentialName: `${customerId}-${platform}-target`,
        credentialType: 'target',
        credentialAuthType: credentials.type, // for example 'oauth2' or 'key'
        credentialRegion: 'us-east-2',
        credentialSecret: credentials.secret
      })
    }
  ).then(r => r.json());
  
  // 3. Create or get target
  const target = await ensureTarget(platform);
  
  // 4. Create proxy
  const proxy = await fetch(
    `https://api.requestrocket.com/api/clients/${SAAS_CLIENT_ID}/proxies`,
    {
      method: 'POST',
      headers: {
        'Authorization': RR_USER_TOKEN,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        proxyName: `${customerId}-${platform}`,
        proxyRegion: 'us-east-2',
        proxyProxyCredentialId: proxyCred.credentials[0].sKey,
        proxyTargetId: target.sKey,
        proxyTargetCredentialId: targetCred.credentials[0].sKey,
        proxyActive: true
      })
    }
  ).then(r => r.json());
  
  // 5. Store mapping in your database
  await db.integrations.create({
    customerId,
    platform,
    proxyId: proxy.proxies[0].sKey,
    proxyProxyCredentialId: proxyCred.credentials[0].sKey,
    proxyUrl: `https://us-east-2.requestrocket.com/api/${proxy.proxies[0].sKey}`,
    customerApiKey: customerKey
  });
  
  return {
    proxyUrl: `https://us-east-2.requestrocket.com/api/${proxy.proxies[0].sKey}`,
    apiKey: customerKey
  };
}
def create_customer_integration(customer_id, integration):
    """Create integration for a new customer"""
    platform = integration['platform']
    credentials = integration['credentials']
    customer_key = generate_secure_key()
    
    # 1. Create proxy credential for your customer
    proxy_cred_response = requests.post(
        f'https://api.requestrocket.com/api/clients/{SAAS_CLIENT_ID}/credentials',
        headers={
            'Authorization': RR_USER_TOKEN,
            'Content-Type': 'application/json'
        },
        json={
            'credentialName': f'{customer_id}-proxy-{platform}',
            'credentialType': 'proxy',
            'credentialAuthType': 'key',
            'credentialRegion': 'us-east-2',
            'credentialSecret': {
                'key': 'Authorization',
                'value': customer_key,
                'addToHeader': True
            }
        }
    )
    proxy_cred = proxy_cred_response.json()
    
    # 2. Create target credential (customer's third-party creds)
    target_cred_response = requests.post(
        f'https://api.requestrocket.com/api/clients/{SAAS_CLIENT_ID}/credentials',
        headers={
            'Authorization': RR_USER_TOKEN,
            'Content-Type': 'application/json'
        },
        json={
            'credentialName': f'{customer_id}-{platform}-target',
            'credentialType': 'target',
            'credentialAuthType': credentials['type'],
            'credentialRegion': 'us-east-2',
            'credentialSecret': credentials['secret']
        }
    )
    target_cred = target_cred_response.json()
    
    # 3. Create or get target
    target = ensure_target(platform)
    
    # 4. Create proxy
    proxy_response = requests.post(
        f'https://api.requestrocket.com/api/clients/{SAAS_CLIENT_ID}/proxies',
        headers={
            'Authorization': RR_USER_TOKEN,
            'Content-Type': 'application/json'
        },
        json={
            'proxyName': f'{customer_id}-{platform}',
            'proxyRegion': 'us-east-2',
            'proxyProxyCredentialId': proxy_cred['credentials'][0]['sKey'],
            'proxyTargetId': target['targets'][0]['sKey'],
            'proxyTargetCredentialId': target_cred['credentials'][0]['sKey'],
            'proxyActive': True
        }
    )
    proxy = proxy_response.json()
    
    # 5. Store mapping in your database
    db.integrations.create({
        'customerId': customer_id,
        'platform': platform,
        'proxyId': proxy['proxies'][0]['sKey'],
        'proxyProxyCredentialId': proxy_cred['credentials'][0]['sKey'],
        'proxyUrl': f"https://us-east-2.requestrocket.com/api/{proxy['proxies'][0]['sKey']}",
        'customerApiKey': customer_key
    })
    
    return {
        'proxyUrl': f"https://us-east-2.requestrocket.com/api/{proxy['proxies'][0]['sKey']}",
        'apiKey': customer_key
    }
type Integration struct {
    Platform    string                 `json:"platform"`
    Credentials map[string]interface{} `json:"credentials"`
}

type IntegrationResult struct {
    ProxyURL string `json:"proxyUrl"`
    APIKey   string `json:"apiKey"`
}

func createCustomerIntegration(customerID string, integration Integration) (*IntegrationResult, error) {
    // 1. Create proxy credential
    proxyCredPayload := map[string]interface{}{
        "credentialName": fmt.Sprintf("%s-proxy-%s", customerID, integration.Platform),
        "credentialType": "proxy",
        "credentialAuthType":       "key",
        "credentialRegion":         "us-east-2",
        "credentialSecret": map[string]interface{}{
            "key":  "Authorization",
            "value": generateSecureKey(),
            "addToHeader": true,
        },
    }
    
    proxyCred, err := createCredential(SAAS_CLIENT_ID, proxyCredPayload)
    if err != nil {
        return nil, err
    }
    
    // 2. Create target credential
    targetCredPayload := map[string]interface{}{
        "credentialName": fmt.Sprintf("%s-%s-target", customerID, integration.Platform),
        "credentialType": "target",
        "credentialAuthType":       integration.Credentials["type"],
        "credentialRegion":         "us-east-2",
        "credentialSecret":         integration.Credentials["secret"],
    }
    
    targetCred, err := createCredential(SAAS_CLIENT_ID, targetCredPayload)
    if err != nil {
        return nil, err
    }
    
    // 3. Create or get target
    target, err := ensureTarget(integration.Platform)
    if err != nil {
        return nil, err
    }
    
    // 4. Create proxy
    proxyPayload := map[string]interface{}{
        "proxyName":          fmt.Sprintf("%s-%s", customerID, integration.Platform),
        "proxyRegion":             "us-east-2",
        "proxyProxyCredentialId":  proxyCred["sKey"],
        "proxyTargetId":           target["sKey"],
        "proxyTargetCredentialId": targetCred["sKey"],
        "proxyActive":             true,
    }
    
    proxy, err := createProxy(SAAS_CLIENT_ID, proxyPayload)
    if err != nil {
        return nil, err
    }
    
    // 5. Store mapping in database
    err = db.Integrations.Create(map[string]interface{}{
        "customerId":        customerID,
        "platform":          integration.Platform,
        "proxyId":           proxy["proxyId"],
        "proxyProxyCredentialId": proxyCred["sKey"],
        "proxyUrl":          fmt.Sprintf("https://us-east-2.requestrocket.com/api/%s", proxy["sKey"]),
        "customerApiKey":    proxyCred["secret"].(map[string]interface{})["value"],
    })
    
    if err != nil {
        return nil, err
    }
    
    return &IntegrationResult{
        ProxyURL: fmt.Sprintf("https://us-east-2.requestrocket.com/api/%s", proxy["sKey"]),
        APIKey:   proxyCred["secret"].(map[string]interface{})["value"].(string),
    }, nil
}
public class IntegrationResult {
    public String proxyUrl;
    public String apiKey;
}

public IntegrationResult createCustomerIntegration(
    String customerId, 
    Map<String, Object> integration
) throws IOException {
    String platform = (String) integration.get("platform");
    Map<String, Object> credentials = (Map<String, Object>) integration.get("credentials");
    
    // 1. Create proxy credential
    Map<String, Object> proxyCredPayload = new HashMap<>();
    proxyCredPayload.put("credentialName", customerId + "-proxy-" + platform);
    proxyCredPayload.put("credentialType", "proxy");
    proxyCredPayload.put("credentialAuthType", "key");
    proxyCredPayload.put("credentialRegion", "us-east-2");
    
    Map<String, Object> proxySecret = new HashMap<>();
    proxySecret.put("key", "Authorization");
    proxySecret.put("value", generateSecureKey());
    proxySecret.put("addToHeader", true);
    proxyCredPayload.put("credentialSecret", proxySecret);
    
    Map<String, Object> proxyCred = createCredential(SAAS_CLIENT_ID, proxyCredPayload);
    
    // 2. Create target credential
    Map<String, Object> targetCredPayload = new HashMap<>();
    targetCredPayload.put("credentialName", customerId + "-" + platform + "-target");
    targetCredPayload.put("credentialType", "target");
    targetCredPayload.put("credentialAuthType", credentials.get("type"));
    targetCredPayload.put("credentialRegion", "us-east-2");
    targetCredPayload.put("credentialSecret", credentials.get("secret"));
    
    Map<String, Object> targetCred = createCredential(SAAS_CLIENT_ID, targetCredPayload);
    
    // 3. Create or get target
    Map<String, Object> target = ensureTarget(platform);
    
    // 4. Create proxy
    Map<String, Object> proxyPayload = new HashMap<>();
    proxyPayload.put("proxyName", customerId + "-" + platform);
    proxyPayload.put("proxyRegion", "us-east-2");
    proxyPayload.put("proxyProxyCredentialId", proxyCred.get("sKey"));
    proxyPayload.put("proxyTargetId", target.get("sKey"));
    proxyPayload.put("proxyTargetCredentialId", targetCred.get("sKey"));
    proxyPayload.put("proxyActive", true);
    
    Map<String, Object> proxy = createProxy(SAAS_CLIENT_ID, proxyPayload);
    
    // 5. Store mapping in database
    Map<String, Object> dbRecord = new HashMap<>();
    dbRecord.put("customerId", customerId);
    dbRecord.put("platform", platform);
    dbRecord.put("proxyId", proxy.get("proxyId"));
    dbRecord.put("proxyProxyCredentialId", proxyCred.get("sKey"));
    dbRecord.put("proxyUrl", "https://us-east-2.requestrocket.com/api/" + proxy.get("sKey"));
    
    Map<String, String> secret = (Map<String, String>) proxyCred.get("secret");
    dbRecord.put("customerApiKey", secret.get("value"));
    
    db.integrations.create(dbRecord);
    
    IntegrationResult result = new IntegrationResult();
    result.proxyUrl = "https://us-east-2.requestrocket.com/api/" + proxy.get("sKey");
    result.apiKey = secret.get("value");
    
    return result;
}

Make Requests on Behalf of Customers

When your SaaS needs to sync data or perform operations:

# Make request through customer's proxy
# Get the customer's proxy URL and API key from your database
curl -X GET "https://us-east-2.requestrocket.com/api/my-proxy/api/customers" \
  -H "Authorization: customer-proxy-api-key" \
  -H "Content-Type: application/json"

# POST request example
curl -X POST "https://us-east-2.requestrocket.com/api/my-proxy/api/orders" \
  -H "Authorization: customer-proxy-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "prod_123",
    "quantity": 5
  }'
async function syncCustomerData(customerId, platform) {
  // Get customer's integration
  const integration = await db.integrations.findOne({
    customerId,
    platform
  });
  
  // Make request through their proxy
  const response = await fetch(
    `${integration.proxyUrl}/api/customers`,
    {
      headers: {
        'Authorization': integration.customerApiKey,
        'Content-Type': 'application/json'
      }
    }
  );
  
  const data = await response.json();
  
  // Process and store data
  await processCustomerData(customerId, platform, data);
  
  return data;
}
def sync_customer_data(customer_id, platform):
    """Sync data for a specific customer"""
    # Get customer's integration
    integration = db.integrations.find_one({
        'customerId': customer_id,
        'platform': platform
    })
    
    # Make request through their proxy
    response = requests.get(
        f"{integration['proxyUrl']}/api/customers",
        headers={
            'Authorization': integration['customerApiKey'],
            'Content-Type': 'application/json'
        }
    )
    
    data = response.json()
    
    # Process and store data
    process_customer_data(customer_id, platform, data)
    
    return data
func syncCustomerData(customerID, platform string) (interface{}, error) {
    // Get customer's integration
    integration, err := db.Integrations.FindOne(map[string]interface{}{
        "customerId": customerID,
        "platform":   platform,
    })
    if err != nil {
        return nil, err
    }
    
    // Make request through their proxy
    req, err := http.NewRequest(
        "GET",
        integration["proxyUrl"].(string)+"/api/customers",
        nil,
    )
    if err != nil {
        return nil, err
    }
    
    req.Header.Set("Authorization", integration["customerApiKey"].(string))
    req.Header.Set("Content-Type", "application/json")
    
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    
    var data interface{}
    if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
        return nil, err
    }
    
    // Process and store data
    if err := processCustomerData(customerID, platform, data); err != nil {
        return nil, err
    }
    
    return data, nil
}
public Object syncCustomerData(String customerId, String platform) throws IOException {
    // Get customer's integration
    Map<String, Object> integration = db.integrations.findOne(
        Map.of("customerId", customerId, "platform", platform)
    );
    
    // Make request through their proxy
    String url = integration.get("proxyUrl") + "/api/customers";
    
    Request request = new Request.Builder()
        .url(url)
        .header("Authorization", integration.get("customerApiKey"))
        .header("Content-Type", "application/json")
        .get()
        .build();
    
    try (Response response = httpClient.newCall(request).execute()) {
        if (!response.isSuccessful()) {
            throw new IOException("Request failed: " + response);
        }
        
        String json = response.body().string();
        Object data = gson.fromJson(json, Object.class);
        
        // Process and store data
        processCustomerData(customerId, platform, data);
        
        return data;
    }
}

Enable Customer Self-Service

Let customers make their own API calls:

// Provide customers with their integration details
app.get('/api/integrations/:platform', authenticateCustomer, async (req, res) => {
  const { customerId } = req.user;
  const { platform } = req.params;
  
  const integration = await db.integrations.findOne({
    customerId,
    platform
  });
  
  if (!integration) {
    return res.status(404).json({ error: 'Integration not found' });
  }
  
  res.json({
    platform,
    proxyUrl: integration.proxyUrl,
    apiKey: integration.customerApiKey, // Give them the key
    documentation: `/docs/integrations/${platform}`
  });
});

Customers can then use your proxy directly:

// Customer's code
const response = await fetch(
  'https://us-east-2.requestrocket.com/api/my-proxy/orders',
  {
    headers: {
      'Authorization': 'customer-api-key-from-your-saas',
      'Content-Type': 'application/json'
    }
  }
);

Advanced Patterns

The following patterns extend the core integration with organisation isolation, request rules, asynchronous delivery, and usage reporting.

Multi-Client Architecture

For enterprise customers or compliance requirements, create separate RequestRocket clients:

# Create dedicated RequestRocket client for enterprise customer
curl -X POST "https://api.requestrocket.com/api/clients" \
  -H "Authorization: $RR_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clientName": "Enterprise: Acme Corp"
  }'

# 201 { "clients": [{ "clientId": "c4d8e1f0-6a22-4b9c-8d33-1e7a5b0c2d44", "clientName": "Enterprise: Acme Corp", "clientMembers": [] }], "message": "client created successfully" }

# Now create integrations under their dedicated client
curl -X POST "https://api.requestrocket.com/api/clients/c4d8e1f0-6a22-4b9c-8d33-1e7a5b0c2d44/credentials" \
  -H "Authorization: $RR_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "credentialName": "acme-salesforce-proxy",
    "credentialType": "proxy",
    ...
  }'
async function provisionEnterpriseCustomer(customerId, customerName) {
  // Create dedicated RequestRocket client for this customer
  const client = await fetch('https://api.requestrocket.com/api/clients', {
    method: 'POST',
    headers: {
      'Authorization': RR_USER_TOKEN,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      clientName: `Enterprise: ${customerName}`
    })
  }).then(r => r.json());
  
  // Store mapping
  await db.customers.update(customerId, {
    rrClientId: client.clients[0].clientId,
    tier: 'enterprise'
  });
  
  return client;
}

// Now create all their integrations under their own client
async function createEnterpriseIntegration(customerId, platform, credentials) {
  const customer = await db.customers.findById(customerId);
  const clientId = customer.rrClientId; // Their dedicated client
  
  // Create credentials and proxies under their client
  // ... (same as before but using their clientId)
}
def provision_enterprise_customer(customer_id, customer_name):
    """Create dedicated RequestRocket client for enterprise customer"""
    # Create dedicated client
    response = requests.post(
        'https://api.requestrocket.com/api/clients',
        headers={
            'Authorization': RR_USER_TOKEN,
            'Content-Type': 'application/json'
        },
        json={
            'clientName': f'Enterprise: {customer_name}'
        }
    )
    
    client = response.json()
    
    # Store mapping
    db.customers.update(customer_id, {
        'rrClientId': client['clients'][0]['clientId'],
        'tier': 'enterprise'
    })
    
    return client

def create_enterprise_integration(customer_id, platform, credentials):
    """Create integration under customer's dedicated client"""
    customer = db.customers.find_by_id(customer_id)
    client_id = customer['rrClientId']  # Their dedicated client
    
    # Create credentials and proxies under their client
    # ... (same as before but using their client_id)
func provisionEnterpriseCustomer(customerID, customerName string) (*Client, error) {
    // Create dedicated RequestRocket client
    payload := map[string]string{
        "clientName": fmt.Sprintf("Enterprise: %s", customerName),
    }
    
    jsonData, err := json.Marshal(payload)
    if err != nil {
        return nil, err
    }
    
    req, err := http.NewRequest(
        "POST",
        "https://api.requestrocket.com/api/clients",
        bytes.NewBuffer(jsonData),
    )
    if err != nil {
        return nil, err
    }
    
    req.Header.Set("Authorization", RR_USER_TOKEN)
    req.Header.Set("Content-Type", "application/json")
    
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    
    var client Client
    if err := json.NewDecoder(resp.Body).Decode(&client); err != nil {
        return nil, err
    }
    
    // Store mapping
    err = db.Customers.Update(customerID, map[string]interface{}{
        "rrClientId": client.Clients[0].ClientID,
        "tier":       "enterprise",
    })
    
    return &client, err
}

func createEnterpriseIntegration(customerID, platform string, credentials map[string]interface{}) error {
    customer, err := db.Customers.FindByID(customerID)
    if err != nil {
        return err
    }
    
    clientID := customer["rrClientId"].(string) // Their dedicated client
    
    // Create credentials and proxies under their client
    // ... (same as before but using their clientID)
    return nil
}
public Client provisionEnterpriseCustomer(String customerId, String customerName) 
    throws IOException {
    // Create dedicated RequestRocket client
    Map<String, String> payload = new HashMap<>();
    payload.put("clientName", "Enterprise: " + customerName);
    
    String json = gson.toJson(payload);
    RequestBody body = RequestBody.create(
        json, 
        MediaType.parse("application/json")
    );
    
    Request request = new Request.Builder()
        .url("https://api.requestrocket.com/api/clients")
        .header("Authorization", RR_USER_TOKEN)
        .header("Content-Type", "application/json")
        .post(body)
        .build();
    
    try (Response response = httpClient.newCall(request).execute()) {
        String responseJson = response.body().string();
        Client client = gson.fromJson(responseJson, Client.class);
        
        // Store mapping
        Map<String, Object> updates = new HashMap<>();
        updates.put("rrClientId", client.clients[0].clientId);
        updates.put("tier", "enterprise");
        db.customers.update(customerId, updates);
        
        return client;
    }
}

public void createEnterpriseIntegration(
    String customerId, 
    String platform, 
    Map<String, Object> credentials
) throws IOException {
    Map<String, Object> customer = db.customers.findById(customerId);
    String clientId = (String) customer.get("rrClientId"); // Their dedicated client
    
    // Create credentials and proxies under their client
    // ... (same as before but using their clientId)
}

Authorization Rules per Customer

Apply different access rules for different customers:

# A window limit is a meter, not a rule. See Limits.
# Deny /admin
curl -X POST "https://api.requestrocket.com/api/clients/$SAAS_CLIENT_ID/proxies/$PROXY_ID/rules" \
  -H "Authorization: $RR_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "effect": "deny",
    "ruleActive": true,
    "priority": 800,
    "path": { "path": { "pattern": "^/admin/" }, "presence": "must_exist" },
    "notes": "Admin endpoints restricted"
  }'

# Deny modifications
curl -X POST "https://api.requestrocket.com/api/clients/$SAAS_CLIENT_ID/proxies/$PROXY_ID/rules" \
  -H "Authorization: $RR_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "effect": "deny",
    "ruleActive": true,
    "priority": 850,
    "methods": ["DELETE", "PUT"],
    "notes": "Read-only access"
  }'
async function applyCustomerRules(customerId, proxyId, ruleConfig) {
  const rules = [];
  
  // Example: Rate limit per customer tier
  if (ruleConfig.tier === 'basic') {
    rules.push({
      effect: 'deny',
      ruleActive: true,
      priority: 900,
      notes: 'A request limit is a meter, not a rule',
    });
  }
  
  // Example: Restrict certain endpoints
  if (ruleConfig.restrictedPaths) {
    for (const path of ruleConfig.restrictedPaths) {
      rules.push({
        effect: 'deny',
        ruleActive: true,
        priority: 800,
        path: { path: { pattern: path }, presence: 'must_exist' },
        notes: `Restricted path for ${customerId}`
      });
    }
  }
  
  // Create rules
  for (const rule of rules) {
    await fetch(
      `https://api.requestrocket.com/api/clients/${SAAS_CLIENT_ID}/proxies/${proxyId}/rules`,
      {
        method: 'POST',
        headers: {
          'Authorization': RR_USER_TOKEN,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(rule)
      }
    );
  }
}
def apply_customer_rules(customer_id, proxy_id, rule_config):
    """Apply authorization rules based on customer tier and config"""
    rules = []
    
    # Example: Rate limit per customer tier
    if rule_config.get('tier') == 'basic':
        rules.append({
            'effect': 'deny',
            'ruleActive': True,
            'priority': 900,
            'notes': 'A request limit is a meter, not a rule'
        })
    
    # Example: Restrict certain endpoints
    if rule_config.get('restrictedPaths'):
        for path in rule_config['restrictedPaths']:
            rules.append({
                'effect': 'deny',
                'ruleActive': True,
                'priority': 800,
                'path': { 'path': { 'pattern': path }, 'presence': 'must_exist' },
                'notes': f'Restricted path for {customer_id}'
            })
    
    # Example: Method restrictions (read-only)
    if rule_config.get('readOnly'):
        rules.append({
            'effect': 'deny',
            'ruleActive': True,
            'priority': 850,
            'methods': ['DELETE', 'PUT', 'PATCH'],
            'notes': f'Read-only access for {customer_id}'
        })
    
    # Create rules
    for rule in rules:
        response = requests.post(
            f'https://api.requestrocket.com/api/clients/{SAAS_CLIENT_ID}/proxies/{proxy_id}/rules',
            headers={
                'Authorization': RR_USER_TOKEN,
                'Content-Type': 'application/json'
            },
            json=rule
        )
        response.raise_for_status()
func applyCustomerRules(customerID, proxyID string, ruleConfig map[string]interface{}) error {
    rules := []map[string]interface{}{}
    
    // Example: Rate limit per customer tier
    if tier, ok := ruleConfig["tier"].(string); ok && tier == "basic" {
        rules = append(rules, map[string]interface{}{
            "effect":   "deny",
            "ruleActive": true,
            "priority": 900,
            "notes":    "A request limit is a meter, not a rule",
        })
    }
    
    // Example: Restrict certain endpoints
    if restrictedPaths, ok := ruleConfig["restrictedPaths"].([]string); ok {
        for _, path := range restrictedPaths {
            rules = append(rules, map[string]interface{}{
                "effect":       "deny",
                "ruleActive":   true,
                "priority":     800,
                "path": map[string]interface{}{
                    "path": map[string]string{"pattern": path},
                    "presence": "must_exist",
                },
                "notes":        fmt.Sprintf("Restricted path for %s", customerID),
            })
        }
    }
    
    // Example: Method restrictions (read-only)
    if readOnly, ok := ruleConfig["readOnly"].(bool); ok && readOnly {
        rules = append(rules, map[string]interface{}{
            "effect":         "deny",
            "ruleActive":     true,
            "priority":       850,
            "methods":        []string{"DELETE", "PUT", "PATCH"},
            "notes":          fmt.Sprintf("Read-only access for %s", customerID),
        })
    }
    
    // Create rules
    for _, rule := range rules {
        jsonData, err := json.Marshal(rule)
        if err != nil {
            return err
        }
        
        url := fmt.Sprintf(
            "https://api.requestrocket.com/api/clients/%s/proxies/%s/rules",
            SAAS_CLIENT_ID,
            proxyID,
        )
        
        req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
        if err != nil {
            return err
        }
        
        req.Header.Set("Authorization", RR_USER_TOKEN)
        req.Header.Set("Content-Type", "application/json")
        
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            return err
        }
        resp.Body.Close()
        
        if resp.StatusCode >= 400 {
            return fmt.Errorf("failed to create rule: %d", resp.StatusCode)
        }
    }
    
    return nil
}
public void applyCustomerRules(
    String customerId, 
    String proxyId, 
    Map<String, Object> ruleConfig
) throws IOException {
    List<Map<String, Object>> rules = new ArrayList<>();
    
    // Example: Rate limit per customer tier
    if ("basic".equals(ruleConfig.get("tier"))) {
        Map<String, Object> rule = new HashMap<>();
        rule.put("effect", "deny");
        rule.put("ruleActive", true);
        rule.put("priority", 900);
        rule.put("notes", "A request limit is a meter, not a rule");
        rules.add(rule);
    }
    
    // Example: Restrict certain endpoints
    if (ruleConfig.containsKey("restrictedPaths")) {
        List<String> restrictedPaths = (List<String>) ruleConfig.get("restrictedPaths");
        for (String path : restrictedPaths) {
            Map<String, Object> rule = new HashMap<>();
            rule.put("effect", "deny");
            rule.put("ruleActive", true);
            rule.put("priority", 800);
            Map<String, Object> pathCheck = new HashMap<>();
            pathCheck.put("path", Map.of("pattern", path));
            pathCheck.put("presence", "must_exist");
            rule.put("path", pathCheck);
            rule.put("notes", "Restricted path for " + customerId);
            rules.add(rule);
        }
    }
    
    // Example: Method restrictions (read-only)
    if (Boolean.TRUE.equals(ruleConfig.get("readOnly"))) {
        Map<String, Object> rule = new HashMap<>();
        rule.put("effect", "deny");
        rule.put("priority", 850);
        rule.put("ruleActive", true);
        rule.put("methods", List.of("DELETE", "PUT", "PATCH"));
        rule.put("notes", "Read-only access for " + customerId);
        rules.add(rule);
    }
    
    // Create rules
    String url = String.format(
        "https://api.requestrocket.com/api/clients/%s/proxies/%s/rules",
        SAAS_CLIENT_ID,
        proxyId
    );
    
    for (Map<String, Object> rule : rules) {
        String json = gson.toJson(rule);
        RequestBody body = RequestBody.create(
            json, 
            MediaType.parse("application/json")
        );
        
        Request request = new Request.Builder()
            .url(url)
            .header("Authorization", RR_USER_TOKEN)
            .header("Content-Type", "application/json")
            .post(body)
            .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Failed to create rule: " + response.code());
            }
        }
    }
}

Webhook Forwarding

Use the Async API when your application accepts work now and RequestRocket should process the proxy request asynchronously. This is the canonical webhook-forwarding example for the developer guides.

# Forward webhook using async endpoint
# Replace /api/ with /async/ in the proxy URL
curl -X POST "https://us-east-2.requestrocket.com/async/my-proxy/webhooks" \
  -H "Authorization: customer-proxy-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "order.created",
    "orderId": "ord_123",
    "timestamp": "2026-01-24T10:30:00Z",
    "data": {
      "amount": 99.99,
      "currency": "USD"
    }
  }'

# Response:
# {
#   "message": "Request accepted for async processing",
#   "requestId": "f3a6c812-9d04-4e75-b1a8-2c0e5d7f9b31",
#   "status": "queued"
# }

# Check webhook delivery status
curl -X GET "https://api.requestrocket.com/api/clients/$SAAS_CLIENT_ID/proxies/$PROXY_ID/requests/$REQUEST_ID" \
  -H "Authorization: $RR_USER_TOKEN"
async function forwardWebhook(customerId, platform, webhookData) {
  const integration = await db.integrations.findOne({
    customerId,
    platform
  });
  
  // Use async endpoint for reliability
  const asyncUrl = integration.proxyUrl.replace('/api/', '/async/');
  
  const response = await fetch(`${asyncUrl}/webhooks`, {
    method: 'POST',
    headers: {
      'Authorization': integration.customerApiKey,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(webhookData)
  });
  
  const { requestId } = await response.json();
  
  // Track webhook delivery
  await db.webhooks.create({
    customerId,
    platform,
    requestId,
    status: 'queued',
    payload: webhookData
  });
  
  return requestId;
}
def forward_webhook(customer_id, platform, webhook_data):
    """Forward webhook using async API for reliability"""
    integration = db.integrations.find_one({
        'customerId': customer_id,
        'platform': platform
    })
    
    # Use async endpoint for reliability
    async_url = integration['proxyUrl'].replace('/api/', '/async/')
    
    response = requests.post(
        f"{async_url}/webhooks",
        headers={
            'Authorization': integration['customerApiKey'],
            'Content-Type': 'application/json'
        },
        json=webhook_data
    )
    
    result = response.json()
    request_id = result['requestId']
    
    # Track webhook delivery
    db.webhooks.create({
        'customerId': customer_id,
        'platform': platform,
        'requestId': request_id,
        'status': 'queued',
        'payload': webhook_data
    })
    
    return request_id
func forwardWebhook(customerID, platform string, webhookData map[string]interface{}) (string, error) {
    // Get integration
    integration, err := db.Integrations.FindOne(map[string]interface{}{
        "customerId": customerID,
        "platform":   platform,
    })
    if err != nil {
        return "", err
    }
    
    // Use async endpoint for reliability
    proxyURL := integration["proxyUrl"].(string)
    asyncURL := strings.Replace(proxyURL, "/api/", "/async/", 1)
    
    // Marshal webhook data
    jsonData, err := json.Marshal(webhookData)
    if err != nil {
        return "", err
    }
    
    // Send to async endpoint
    req, err := http.NewRequest(
        "POST",
        asyncURL+"/webhooks",
        bytes.NewBuffer(jsonData),
    )
    if err != nil {
        return "", err
    }
    
    req.Header.Set("Authorization", integration["customerApiKey"].(string))
    req.Header.Set("Content-Type", "application/json")
    
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()
    
    var result struct {
        RequestID string `json:"requestId"`
    }
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        return "", err
    }
    
    // Track webhook delivery
    err = db.Webhooks.Create(map[string]interface{}{
        "customerId": customerID,
        "platform":   platform,
        "requestId":  result.RequestID,
        "status":     "queued",
        "payload":    webhookData,
    })
    
    return result.RequestID, err
}
public String forwardWebhook(
    String customerId, 
    String platform, 
    Map<String, Object> webhookData
) throws IOException {
    // Get integration
    Map<String, Object> integration = db.integrations.findOne(
        Map.of("customerId", customerId, "platform", platform)
    );
    
    // Use async endpoint for reliability
    String proxyUrl = (String) integration.get("proxyUrl");
    String asyncUrl = proxyUrl.replace("/api/", "/async/");
    
    // Send to async endpoint
    String json = gson.toJson(webhookData);
    RequestBody body = RequestBody.create(
        json, 
        MediaType.parse("application/json")
    );
    
    Request request = new Request.Builder()
        .url(asyncUrl + "/webhooks")
        .header("Authorization", integration.get("customerApiKey"))
        .header("Content-Type", "application/json")
        .post(body)
        .build();
    
    try (Response response = httpClient.newCall(request).execute()) {
        String responseJson = response.body().string();
        JsonObject result = gson.fromJson(responseJson, JsonObject.class);
        String requestId = result.get("requestId").getAsString();
        
        // Track webhook delivery
        Map<String, Object> webhookRecord = new HashMap<>();
        webhookRecord.put("customerId", customerId);
        webhookRecord.put("platform", platform);
        webhookRecord.put("requestId", requestId);
        webhookRecord.put("status", "queued");
        webhookRecord.put("payload", webhookData);
        
        db.webhooks.create(webhookRecord);
        
        return requestId;
    }
}

Monitoring Customer Usage

Query request logs for each customer proxy and aggregate the results in your application.

# Get request logs for a specific proxy
curl -X GET "https://api.requestrocket.com/api/clients/$SAAS_CLIENT_ID/proxies/$PROXY_ID/requests" \
  -H "Authorization: $RR_USER_TOKEN"

# Response:
# {
#   "message": "Success",
#   "totalRequests": 1,
#   "requests": [
#     { "proxyData": { "status": 200, "duration": 0.234 } }
#   ]
# }

# Get aggregated stats for all customer integrations
# (Requires iterating through each customer's proxies)
for proxy_id in $(get_customer_proxy_ids); do
  curl -X GET "https://api.requestrocket.com/api/clients/$SAAS_CLIENT_ID/proxies/$proxy_id/requests" \
    -H "Authorization: $RR_USER_TOKEN"
done
async function getCustomerUsageStats(customerId, startDate, endDate) {
  const integrations = await db.integrations.find({ customerId });
  
  const stats = await Promise.all(
    integrations.map(async (integration) => {
      const response = await fetch(
        `https://api.requestrocket.com/api/clients/${SAAS_CLIENT_ID}/proxies/${integration.proxyId}/requests?` +
        `processedAfter=${startDate}&processedBefore=${endDate}`,
        {
          headers: { 'Authorization': RR_USER_TOKEN }
        }
      );
      
      const body = await response.json();
      const data = body.requests || [];
      
      return {
        platform: integration.platform,
        totalRequests: body.totalRequests,
        successful: data.filter(r => r.proxyData && r.proxyData.status >= 200 && r.proxyData.status < 300).length,
        failed: data.filter(r => r.proxyData && (r.proxyData.status < 200 || r.proxyData.status >= 300)).length,
        avgDuration: data.reduce((sum, r) => sum + (r.proxyData?.duration || 0), 0) / (data.length || 1)
      };
    })
  );
  
  return {
    customerId,
    period: { startDate, endDate },
    integrations: stats,
    total: stats.reduce((sum, s) => sum + s.totalRequests, 0)
  };
}
def get_customer_usage_stats(customer_id, start_date, end_date):
    """Track usage across all customer integrations"""
    integrations = db.integrations.find({'customerId': customer_id})
    
    stats = []
    for integration in integrations:
        response = requests.get(
            f"https://api.requestrocket.com/api/clients/{SAAS_CLIENT_ID}/proxies/{integration['proxyId']}/requests",
            params={
                'processedAfter': start_date,
                'processedBefore': end_date
            },
            headers={'Authorization': RR_USER_TOKEN}
        )
        
        body = response.json()
        data = body.get('requests') or []
        
        total_requests = body.get('totalRequests', len(data))
        successful = len([r for r in data if 200 <= (r.get('proxyData') or {}).get('status', 0) < 300])
        failed = len([r for r in data if (r.get('proxyData') or {}).get('status', 0) >= 300])
        avg_duration = sum((r.get('proxyData') or {}).get('duration') or 0 for r in data) / total_requests if total_requests else 0
        
        stats.append({
            'platform': integration['platform'],
            'totalRequests': total_requests,
            'successful': successful,
            'failed': failed,
            'avgDuration': avg_duration
        })
    
    return {
        'customerId': customer_id,
        'period': {'startDate': start_date, 'endDate': end_date},
        'integrations': stats,
        'total': sum(s['totalRequests'] for s in stats)
    }
type UsageStats struct {
    Platform      string  `json:"platform"`
    TotalRequests int     `json:"totalRequests"`
    Successful    int     `json:"successful"`
    Failed        int     `json:"failed"`
    AvgDuration   float64 `json:"avgDuration"`
}

type CustomerUsage struct {
    CustomerID   string                 `json:"customerId"`
    Period       map[string]string      `json:"period"`
    Integrations []UsageStats           `json:"integrations"`
    Total        int                    `json:"total"`
}

func getCustomerUsageStats(customerID, startDate, endDate string) (*CustomerUsage, error) {
    integrations, err := db.Integrations.Find(map[string]interface{}{
        "customerId": customerID,
    })
    if err != nil {
        return nil, err
    }
    
    stats := []UsageStats{}
    totalRequests := 0
    
    for _, integration := range integrations {
        url := fmt.Sprintf(
            "https://api.requestrocket.com/api/clients/%s/proxies/%s/requests?processedAfter=%s&processedBefore=%s",
            SAAS_CLIENT_ID,
            integration["proxyId"],
            startDate,
            endDate,
        )
        
        req, _ := http.NewRequest("GET", url, nil)
        req.Header.Set("Authorization", RR_USER_TOKEN)
        
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            return nil, err
        }
        defer resp.Body.Close()
        
        var result struct {
            TotalRequests int `json:"totalRequests"`
            Requests []struct {
                ProxyData struct {
                    Status   int     `json:"status"`
                    Duration float64 `json:"duration"`
                } `json:"proxyData"`
            } `json:"requests"`
        }
        
        json.NewDecoder(resp.Body).Decode(&result)
        
        successful := 0
        failed := 0
        var totalDuration float64
        
        for _, r := range result.Requests {
            if r.ProxyData.Status >= 200 && r.ProxyData.Status < 300 {
                successful++
            } else if r.ProxyData.Status >= 300 {
                failed++
            }
            totalDuration += r.ProxyData.Duration
        }
        
        avgDuration := float64(0)
        if len(result.Requests) > 0 {
            avgDuration = totalDuration / float64(len(result.Requests))
        }
        
        stat := UsageStats{
            Platform:      integration["platform"].(string),
            TotalRequests: result.TotalRequests,
            Successful:    successful,
            Failed:        failed,
            AvgDuration:   avgDuration,
        }
        
        stats = append(stats, stat)
        totalRequests += result.TotalRequests
    }
    
    return &CustomerUsage{
        CustomerID: customerID,
        Period: map[string]string{
            "startDate": startDate,
            "endDate":   endDate,
        },
        Integrations: stats,
        Total:        totalRequests,
    }, nil
}
public class UsageStats {
    public String platform;
    public int totalRequests;
    public int successful;
    public int failed;
    public double avgDuration;
}

public class CustomerUsage {
    public String customerId;
    public Map<String, String> period;
    public List<UsageStats> integrations;
    public int total;
}

public CustomerUsage getCustomerUsageStats(
    String customerId, 
    String startDate, 
    String endDate
) throws IOException {
    List<Map<String, Object>> integrations = db.integrations.find(
        Map.of("customerId", customerId)
    );
    
    List<UsageStats> stats = new ArrayList<>();
    int totalRequests = 0;
    
    for (Map<String, Object> integration : integrations) {
        String url = String.format(
            "https://api.requestrocket.com/api/clients/%s/proxies/%s/requests?processedAfter=%s&processedBefore=%s",
            SAAS_CLIENT_ID,
            integration.get("proxyId"),
            startDate,
            endDate
        );
        
        Request request = new Request.Builder()
            .url(url)
            .header("Authorization", RR_USER_TOKEN)
            .get()
            .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            String json = response.body().string();
            JsonObject result = gson.fromJson(json, JsonObject.class);
            JsonArray data = result.getAsJsonArray("requests");
            
            int successful = 0;
            int failed = 0;
            double totalDuration = 0;
            
            for (JsonElement element : data) {
                JsonObject proxyData = element.getAsJsonObject().getAsJsonObject("proxyData");
                int status = proxyData.get("status").getAsInt();
                
                if (status >= 200 && status < 300) {
                    successful++;
                } else if (status >= 300) {
                    failed++;
                }
                
                if (proxyData.has("duration") && !proxyData.get("duration").isJsonNull()) {
                    totalDuration += proxyData.get("duration").getAsDouble();
                }
            }
            
            UsageStats stat = new UsageStats();
            stat.platform = (String) integration.get("platform");
            stat.totalRequests = result.get("totalRequests").getAsInt();
            stat.successful = successful;
            stat.failed = failed;
            stat.avgDuration = data.size() > 0 ? totalDuration / data.size() : 0;
            
            stats.add(stat);
            totalRequests += data.size();
        }
    }
    
    CustomerUsage usage = new CustomerUsage();
    usage.customerId = customerId;
    usage.period = Map.of("startDate", startDate, "endDate", endDate);
    usage.integrations = stats;
    usage.total = totalRequests;
    
    return usage;
}

Security Checklist

  • ✅ Never expose RequestRocket user tokens to customers
  • ✅ Use unique proxy credentials per customer
  • ✅ Implement authorization rules for access control
  • ✅ Rotate credentials regularly
  • ✅ Monitor for unusual activity
  • ✅ Audit access logs periodically
  • ✅ Encrypt data in transit and at rest
  • ✅ Follow least privilege principle

Next

On this page