RequestRocketRequestRocketDocs
OrganisationsPlans and billing

Plans and billing API

Read the plan, renew, top up, and open Stripe.

Plan changes, renewal, and top-up are organisation routes. Stripe routes open a customer, a checkout session, or the billing portal. Promo code responses return the grant name, not the redemption code.

On this page

Endpoints

MethodPathWhat it does
GET/api/clients/:clientId/planRead the plan
PUT/api/clients/:clientId/planRequest a plan change
POST/api/clients/:clientId/plan/renewRenew a lapsed plan
POST/api/clients/:clientId/plan/topupRequest a manual top-up
GET/api/clients/:clientId/subscriptionsList subscriptions
POST/api/clients/:clientId/stripe_sessionStart a Stripe checkout session
POST/api/clients/:clientId/stripe_portalOpen the billing portal
GET/api/clients/:clientId/customerRead the Stripe customer
GET/api/clients/:clientId/configurationsRead configuration
PUT/api/clients/:clientId/configurationsUpdate configuration
GET/api/clients/:clientId/promocodesList applied grants
POST/api/clients/:clientId/promocodesRedeem a code

Read the plan

GET /api/clients/:clientId/plan returns the current plan.

Request

curl -X GET "https://api.requestrocket.com/api/clients/:clientId/plan" \
  -H "Authorization: u-your-token"
import axios from "axios";

const response = await axios.request({
  method: "GET",
  url: "https://api.requestrocket.com/api/clients/:clientId/plan",
  headers: {
    "Authorization": "u-your-token",
  }
});

console.log(response.status, response.data);
import requests

response = requests.request(
    "GET",
    "https://api.requestrocket.com/api/clients/:clientId/plan",
    headers={
        "Authorization": "u-your-token",
    }
)
print(response.status_code, response.json())
package main

import (
    "fmt"
    "io"
    "net/http"
    "strings"
)

func main() {
    var payload io.Reader
    req, _ := http.NewRequest("GET", "https://api.requestrocket.com/api/clients/:clientId/plan", payload)
    req.Header.Set("Authorization", "u-your-token")
    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    fmt.Println(resp.StatusCode, string(body))
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Example {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.requestrocket.com/api/clients/:clientId/plan"))
            .method("GET", HttpRequest.BodyPublishers.noBody())
            .header("Authorization", "u-your-token")
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.statusCode());
        System.out.println(response.body());
    }
}

Responses

{
  "plan": {
    "planTier": "team",
    "planStatus": "active",
    "planPendingTier": null,
    "planPendingInvoiceId": null,
    "planPendingEffectiveAt": null,
    "planExpiresAt": null,
    "planRenewedAt": "2026-11-02T07:30:00.000Z",
    "planBillingAnchor": null,
    "featureOverrides": [],
    "promoOverrides": [],
    "effectivePlanTier": "team",
    "features": [
      "proxy_auth_key",
      "mcp_entrypoint"
    ],
    "displayName": "Team",
    "prices": {
      "basic": 0,
      "team": 1
    },
    "displayNames": {
      "basic": "Basic",
      "team": "Team",
      "enterprise_basic": "Enterprise Basic",
      "enterprise_security": "Enterprise Security",
      "enterprise_governance": "Enterprise Governance",
      "enterprise_custom": "Enterprise Custom"
    },
    "tiers": [
      "basic",
      "team",
      "enterprise_basic",
      "enterprise_security",
      "enterprise_governance",
      "enterprise_custom"
    ]
  },
  "message": "Success"
}
{
  "message": "Client not found"
}
{
  "message": "Unauthorized"
}
{
  "Message": "User is not authorized to access this resource with an explicit deny in an identity-based policy"
}
{
  "message": "method / endpoint not supported"
}

Query parameters

None.

Response

AttributeTypeDescription
plan.planTierstringStored tier: basic, team, enterprise_basic, enterprise_security, enterprise_governance, or enterprise_custom.
plan.planStatusstringactive, upgrade_requested, downgrade_scheduled, payment_failed, or expired.
plan.effectivePlanTierstringTier in effect. It can differ from planTier while a change is pending.
plan.displayNamestringLabel for the effective tier.
plan.featuresarray of stringFeature ids enabled for the effective tier.
plan.pricesobjectPrice for each tier id, after any plan rate.
plan.displayNamesobjectLabel for every tier id.
plan.tiersarray of stringTier ids in order.
plan.planPendingTierstring or nullTier waiting to start.
plan.planPendingInvoiceIdstring or nullStripe invoice for a pending upgrade or renewal.
plan.planPendingEffectiveAtstring or nullWhen a scheduled downgrade takes effect.
plan.planExpiresAtstring or nullEnd of the current paid period.
plan.planRenewedAtstring or nullWhen the current period started.
plan.planBillingAnchornumber or nullDay of the month used for the billing period.
plan.featureOverridesarray of stringExtra features assigned to this organisation.
plan.promoOverridesarray of stringFeatures granted by promotional codes.
messagestringSuccess on a read.

Request a plan change

PUT /api/clients/:clientId/plan asks to move the organisation to another tier.

Request body

ParameterTypeRequiredDescription
planTierstring✓basic, team, enterprise_basic, enterprise_security, enterprise_governance, or enterprise_custom. enterprise_custom is assigned by RequestRocket.

Returns plan in the same shape as the read call. An upgrade billed through Stripe also returns invoiceId, and planStatus becomes upgrade_requested. A downgrade sets planStatus to downgrade_scheduled and planPendingEffectiveAt to the end of the current period. Sending the current tier while a change is pending cancels that change.

Renew the plan

POST /api/clients/:clientId/plan/renew renews a plan that is expired or payment-failed.

Request

curl -X POST "https://api.requestrocket.com/api/clients/:clientId/plan/renew" \
  -H "Authorization: u-your-token"
import axios from "axios";

const response = await axios.request({
  method: "POST",
  url: "https://api.requestrocket.com/api/clients/:clientId/plan/renew",
  headers: {
    "Authorization": "u-your-token",
  }
});

console.log(response.status, response.data);
import requests

response = requests.request(
    "POST",
    "https://api.requestrocket.com/api/clients/:clientId/plan/renew",
    headers={
        "Authorization": "u-your-token",
    }
)
print(response.status_code, response.json())
package main

import (
    "fmt"
    "io"
    "net/http"
    "strings"
)

func main() {
    var payload io.Reader
    req, _ := http.NewRequest("POST", "https://api.requestrocket.com/api/clients/:clientId/plan/renew", payload)
    req.Header.Set("Authorization", "u-your-token")
    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    fmt.Println(resp.StatusCode, string(body))
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Example {
    public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.requestrocket.com/api/clients/:clientId/plan/renew"))
            .method("POST", HttpRequest.BodyPublishers.noBody())
            .header("Authorization", "u-your-token")
            .build();
        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.statusCode());
        System.out.println(response.body());
    }
}

Responses

{
  "plan": {
    "planTier": "team",
    "planStatus": "active",
    "planPendingTier": null,
    "planPendingInvoiceId": null,
    "planPendingEffectiveAt": null,
    "planExpiresAt": null,
    "planRenewedAt": "2026-11-02T07:30:00.000Z",
    "planBillingAnchor": null,
    "featureOverrides": [],
    "promoOverrides": [],
    "effectivePlanTier": "team",
    "features": [
      "proxy_auth_key",
      "mcp_entrypoint"
    ],
    "displayName": "Team",
    "prices": {
      "basic": 0,
      "team": 1
    },
    "displayNames": {
      "basic": "Basic",
      "team": "Team",
      "enterprise_basic": "Enterprise Basic",
      "enterprise_security": "Enterprise Security",
      "enterprise_governance": "Enterprise Governance",
      "enterprise_custom": "Enterprise Custom"
    },
    "tiers": [
      "basic",
      "team",
      "enterprise_basic",
      "enterprise_security",
      "enterprise_governance",
      "enterprise_custom"
    ]
  },
  "invoiceId": "in_1Example",
  "message": "Renewal invoice created \u2014 pending payment"
}
{
  "message": "Plan is not expired \u2014 renew is only valid for a lapsed paid plan"
}
{
  "message": "Unauthorized"
}
{
  "Message": "User is not authorized to access this resource with an explicit deny in an identity-based policy"
}
{
  "message": "method / endpoint not supported"
}

Request body

This call has no request body.

Returns plan in the same shape as the read call. A Stripe renewal also returns invoiceId. message is Renewal invoice created — pending payment when an invoice is opened, or Plan renewed when the plan is restored without charging Stripe.

Request a top-up

POST /api/clients/:clientId/plan/topup asks billing to top up an organisation whose top-up method is manual.

Request body

This call has no request body.

Returns message (Top-up request submitted to billing).

List subscriptions

GET /api/clients/:clientId/subscriptions lists the organisation's Stripe subscriptions.

Query parameters

ParameterTypeRequiredDescription
activestring—When omitted, the list includes subscriptions whose status is active and that are not cancelled or set to cancel.

There is no limit, cursor, or page parameter.

Returns subscriptions, an array of Stripe Subscription objects.

Response

AttributeTypeDescription
subscriptions[].idstringStripe subscription id.
subscriptions[].statusstringStripe subscription status.
subscriptions[].customerstringStripe customer id.
subscriptions[].cancel_at_period_endbooleanWhether the subscription ends at the period boundary.
subscriptions[].current_period_startnumberPeriod start, as a Unix timestamp.
subscriptions[].current_period_endnumberPeriod end, as a Unix timestamp.

Start a checkout session

POST /api/clients/:clientId/stripe_session opens a Stripe Checkout session for a subscription. The organisation must already have a Stripe customer.

Request body

ParameterTypeRequiredDescription
successUrlstring✓URL Stripe opens after payment.
cancelUrlstring✓URL Stripe opens when the customer cancels.
quantitynumber✓Quantity for prices that are not metered.
planstring✓basic, team, enterprise_basic, enterprise_security, enterprise_governance, enterprise_custom, Basic, Team, or Business.
metadataobject—Extra key-value pairs stored on the Checkout session. plan is always added.

Returns the Stripe Checkout Session as the response body.

Response

AttributeTypeDescription
idstringCheckout session id.
urlstringURL to send the customer to.
objectstringcheckout.session.
modestringsubscription.
customerstringStripe customer id.
statusstringSession status, such as open.
success_urlstringURL from successUrl.
cancel_urlstringURL from cancelUrl.

Open the billing portal

POST /api/clients/:clientId/stripe_portal opens the Stripe billing portal for the organisation's customer.

Request body

ParameterTypeRequiredDescription
return_urlstring✓URL Stripe opens when the customer leaves the portal.

Returns the Stripe Billing Portal session as the response body.

Response

AttributeTypeDescription
idstringPortal session id.
urlstringURL to send the customer to.
objectstringbilling_portal.session.
customerstringStripe customer id.
return_urlstringURL from the request.

Read the Stripe customer

GET /api/clients/:clientId/customer returns the Stripe customer linked to the organisation.

Query parameters

None.

Response

AttributeTypeDescription
customer.idstringStripe customer id.
customer.emailstringBilling email.
customer.namestringCustomer name.
customer.addressobjectBilling address Stripe has stored.
customer.phonestringPhone number, when set.
customer.metadataobjectIncludes clientId and clientName when RequestRocket created the customer.

Read configuration

GET /api/clients/:clientId/configurations returns one configuration record.

Query parameters

ParameterTypeRequiredDescription
configurationTypestring✓client, user, or msp. Use client for the organisation.

Returns configuration and message.

Response

AttributeTypeDescription
configuration.regionAccessarray of stringRegion codes the organisation may use.
configuration.billingTypestringstripe, marketplace, or invoice.
configuration.billingTostringclient or msp.
configuration.topUpMethodstringautomatic or manual.
configuration.limits.requestsPerMinutenumberPer-minute request cap.
configuration.limits.requestsPerDaynumberPer-day request cap.
configuration.budget.currentnumberCurrent balance. Omitted when an MSP is billed.
configuration.budget.minimumTopUpThresholdnumberBalance that triggers a top-up.
configuration.budget.maximumTopUpThresholdnumberBalance a top-up aims for.
configuration.ratesobjectapiSeconds, storageGB, aiTokens, and plan multipliers. Omitted when an MSP is billed.
configuration.promotionalCodesarray or nullApplied grants. Each item has name, createdAt, and expiresAt. The redemption code is not included.
configuration.planTierstringSame tier values as the plan call.
configuration.planStatusstringSame status values as the plan call.
messagestringSuccess.

Update configuration

PUT /api/clients/:clientId/configurations merges the body into the stored configuration. The same configurationType query parameter as the read call is required.

All fields are optional. Omit a field to leave it unchanged. Plan fields, promotional codes, feature overrides, billing type, who is billed, rates, top-up method, and sharing are not taken from this body. Change the plan with PUT /api/clients/:clientId/plan. Redeem a code with POST /api/clients/:clientId/promocodes.

Request body

ParameterTypeRequiredDescription
regionAccessarray of string—Region codes the organisation may use.
limitsobject—When present, requestsPerMinute and requestsPerDay are both required. Values above 300 per minute or 20,000 per day are stored at those caps.
budgetobject—Applied when billing is stripe and the organisation pays for itself. When present, minimumTopUpThreshold and maximumTopUpThreshold are both required. The minimum is at least 5. The maximum is at least 20 and at least 10 above the minimum. budget.current is not taken from the body.

If you send sharing or rates, include every property those objects require or the call is rejected. A normal caller still does not change the stored sharing or rates.

Returns the saved configuration and message (Configuration updated successfully).

List applied grants

GET /api/clients/:clientId/promocodes returns the grants already on the organisation. The redemption code is not included.

Query parameters

None.

Redeem a code

POST /api/clients/:clientId/promocodes applies a promotional code. The response returns the grant name, not the code.

Request body

ParameterTypeRequiredDescription
codestring✓The redemption code. It is not echoed in the response.

Returns promotionalCodes, applied, alreadyApplied, and message.

Response

AttributeTypeDescription
promotionalCodesarrayGrants now on the organisation. Each item has name, createdAt, and expiresAt.
appliedobjectThe grant this code matches. Same three fields.
alreadyAppliedbooleantrue when that grant was already on the organisation.
messagestringPromotional code applied, or Promotional code already applied.

A 402 on any other call means the organisation is suspended. That code is on Platform limits.

Shared status codes, the 5.5 MB cap, and plan rate limits are on Platform limits.

Next

On this page