Skip to content

Configuring limits

Overview

Once a product is created, customers are able to access the included endpoints without any limitations using the API key issued by Project X.

API providers can use Project X's rich toolkit to define, what limitations customers have when they are subscribed to this product.

Read "Before you begin" to learn more about the product concept.

Limits page

Navigate to Products → choose a product → Limits.

There are three types of limits implemented in Project X:

  • Quotas
  • Rate limits
  • Rejection rules

By combining them you can flexibly configure a wide variety of products.

Quotas

How it works

Quotas represent periodic limits on some metric. That can be almost anything:

  • number of API calls
  • number of uploaded/downloaded bytes
  • number of characters in a text for a Text-to-Speech API
  • internal currency like "coins", "tokens" or "credits"
  • etc.

When Project X API Gateway receives an API call, it calculates, how much of the quota limit the current request will use, checks if the total usage exceeds the limit, and if not — it continues request processing. If the limit is exceeded, the API gateway returns 429 Too Many Requests.

Project X API Gateway performs the following steps in order to check quotas and record quota usage:

graph TD
    input[GET /endpoint1]

    is_response_needed{"Is response
        needed for
        calculations?"}

    proxy_and_wait[Proxy request and wait for response]

    quota_condition_met{"Quota
        usage condition met?"}

    calculate_usage[Calculate quota usage]
    limit_exceeded{"Limit exceeded?"}
    is_hard_limit{"Is hard limit?"}
    return_429[Return 429 Too Many Requests]
    record_usage[Record usage]
    skip_quota_check[Skip quota check]
    proxy[Continue request processing]

    input --> is_response_needed
    is_response_needed -->|Yes| proxy_and_wait
    is_response_needed -->|No| quota_condition_met
    proxy_and_wait --> quota_condition_met
    quota_condition_met -->|No| skip_quota_check
    quota_condition_met -->|Yes| calculate_usage
    calculate_usage --> limit_exceeded
    limit_exceeded -->|No| record_usage
    limit_exceeded -->|Yes| is_hard_limit
    is_hard_limit --> |No| proxy
    is_hard_limit --> |Yes| return_429
    skip_quota_check ----> proxy
    record_usage --> proxy

More about each step below.


Adding quotas

Click "Add quota".

Configure the new quota.


Quota name

This name will be shown to customers on the checkout page. Usually, quota name is the name of the product metric it represents. E.g., "API calls", "Processed images", "Synthesized characters", etc.

Note

There is no need to include time period in the name, Project X will display it to your customers separately.

- Processed images per month
+ Processed images

Check out "What do I charge for?" for more product metric examples.


Quota label

Label for the quota, can contain only numbers, letters and underscore: _

Used internally, can't be changed after the quota is created. Make sure quotas in different products representing the same product metric have the same label — it will allow your customers to seamlessly switch between products.


Quota

The number of quota units included in the product.


Is hard limit

If the checkbox is checked, Project X API Gateway will start rejecting calls to ALL API endpoints associated with the quota once the quota limit is exceeded.

If the checkbox is left unchecked, there will be no hard limit on the metric and the customer can make unlimited calls. Project X will still record usage in cases when the quota usage condition (see below) is met. The recorded usage will be processed by the billing engine.


Endpoints

Here you select endpoints associated with the quota.

Only calls to selected endpoints will use the quota volume.

Example

Say, you have an API with the following endpoints:

  • myfirstapi.example/image/compress
  • myfirstapi.example/image/resize

And you want to have two separate quotas in the product:

  • 100 compressed images per month
  • 200 resized images per month

To achieve that, you need to create two quotas and associate /image/compress endpoint with the first quota, and /image/resize — with the second one.

With that, calls to /image/compress will only use the quota of compressed images and not affect the limit on resized images, while calls to /image/resize will only use the resized images quota.


Quota usage configuration

After you've added a new quota, you can configure, how exactly each call to the associated endpoints uses the quota volume.

By default, each call to the associated endpoint uses 1 unit of quota volume.

This can be changed, and Project X is capable of calculating the quota usage for the current request dynamically.

It means that different calls to the same endpoint can consume a different number of quota units.


Quantity used by a single call

Each endpoint associated with a quota has a field called "Quantity used by a single call".

This field defines, how many quota units are used by each call to this endpoint.


Static quota usage

By default, the field is set to "1", meaning that each call uses 1 quota unit.

Tip

When Project X API Gateway receives a call to an endpoint, it records usage of 1 quota unit by default.

If you want calls to different endpoints to use a different number of quota units, set the respective values in the "Quantity used by a single call" field for each endpoint.


Dynamic quota usage

In addition to static quota usage configuration, Project X API Gateway is capable of calculating quota usage dynamically for each API call.

For that, instead of a static number like 1 or 2, you can specify a JavaScript expression that evaluates to an integer representing the quota usage for the current API call based on the request and/or reponse attributes.

See the examples below.

Example #1

The endpoint GET /prompt/{LLM_MODEL} allows sending textual prompts to two different AI models: gpt3 and gpt4.

The API provider would like calls to gpt4 to consume 2 quota units and calls to gpt3 to consume 1 quota unit.

To achieve that, the expression should evaluate to 2 if the path parameter LLM_MODEL equals to gpt4, 1 otherwise.

E.g.:

path.params.LLM_MODEL == "gpt4" ? 2 : 1

In the form:

Project X API Gateway will check the value of the path parameter and record the usage of 2 quota units if it's gpt4, and 1 quota unit otherwise.

Example #2

The endpoint POST /process accepts a JSON array of elements to process.

The request body looks like:

[
    { "data": "ZDU2OWZlODQtODdiZS00YzZjLTk5ODktYTdjNWRjMmQ5NWJj" },
    { "data": "YTQ5NGUyNWMtNDI2NS00MjkzLWJmYWEtNzY5MjQxZjhlYjI1" },
    { "data": "YWZiOTZhNTAtMWE1Zi00Zjg4LWJmMGMtMWVhODQ2ODY3NmVj" }
]

The API provider would like to record quota usage, equal to the number of elements in the input array. The request body in this example should use 3 quota units.

The JavaScript expression should parse the request body as JSON and return the number of elements:

JSON.parse(request.body).length

In the form:

Calculating usage in the backend

Your API backend can tell Project X directly, how much quota the current request has used.

For instance, if you bill for CPU seconds used to process the request, and Project X is unable to infer that value from the request/response on its own, you can calculate it in your API backend for each request and then tell Project X the actual value it should record by adding a custom header to the response.

The header name doesn't matter, you can use any valid header name, e.g. X-Consumed-Cpu-Seconds.

The expression in this case can be:

response.headers["x-consumed-cpu-seconds"]

In the form:

And that's it. Project X will wait for the response and record the value from the X-Consumed-Cpu-Seconds header as quota usage for the current request.

Tip

There are several variables you can use in your expressions.


Quota usage condition

This field contains a JavaScript expression, which tells Project X whether quota usage should be counted for the current request or not.

The expression must evaluate to a boolean value.

If the expression evaluates to true, quota usage is recorded. If the expression evaluates to false, Project X doesn't record quota usage for the current API call.

Example

The most common use case for this field is to make Project X record quota usage only if response status code is 200.

For that, the Quota usage condition expression will be:

response.statusCode == 200

In the form:

Configured this way, Project X will record quota usage only if the response returned HTTP status code 200 OK.

Tip

There are several variables you can use in your expressions.


Expression variables

The variables described below allow you to configure Project X API Gateway's behavior in a flexible way.

You can use these variables in quota quantity and usage condition expressions.

Path parameters

path.params.* — placeholder values specified in the endpoint URL.

Note

Placeholder names are case-sensitive.

Example

If an endpoint URL is /resource/{resourceId}

and the HTTP request URL is /resource/801d49c2-ca05-42b1-97af-baf0ddf36ba3,

then there will be a variable path.params.resourceId with value "801d49c2-ca05-42b1-97af-baf0ddf36ba3".

path.params.resourceId // "801d49c2-ca05-42b1-97af-baf0ddf36ba3"

Client IP address

request.remote_addr — Client IP address.


Request headers

request.headers['header-name'] — Request header values.

Warning

Header names are lower-case.

Example

request.headers['content-type'] == 'application/json'

Request query string parameters

request.query['query_string_parameter_name'] — Request query string parameters.

Warning

Query string parameter names are case-sensitive.

Example
request.query['page'] > 100

Request body

request.body — Request body.

Example
request.body.length > 1000

Response status code

response.statusCode — HTTP status code of the response from the upstream.

Example
response.statusCode == 200

Response headers

response.headers['header-name'] — Response header values.

Warning

Header names are lower-cased.

Example
response.headers['content-type'] == 'application/json'

Response body

response.body — Raw response body.

Example
response.body.length > 0

Rate limits

A rate limit can be specified per N seconds/minutes/hours.

  1. Click "Add rate limit".

  2. Configure the new rate limit.

    Rate limits can be applied to several endpoints. In that case, the Project X engine will calculate the total request rate for the group of endpoints.

Max burst — an additional number of requests accepted in case the rate limit was exceeded by the user.

Max burst example

  • Rate limit: 1 req/s
  • Max burst: 5 reqs

In case 7 requests hit the Project X API Gateway at the same moment, the first six requests are passed without a delay, and the last, seventh request is rejected. All the following requests are also rejected until the rate of 1 req/s is achieved.

Difference between quotas and rate limits

The difference between rate limits and quotas is that rate limits cap the number of calls within a rolling time window (i.e. last N seconds/minutes/hours), whereas quota periods are calculated starting from the beginning of subscription.

E.g. if there is a subscription started on 01-01-2022 at 00:00:00 and there is a quota of 100 calls per 1 day, then there will be the following time periods:

Quota Time period
100 2022-01-01 00:00:00 — 2022-01-01 23:59:59
100 2022-01-02 00:00:00 — 2022-01-02 23:59:59
100 2022-01-03 00:00:00 — 2022-01-03 23:59:59
100 ...

Rejection rules

Overview

Rejection rules are JavaScript expressions that tell Project X API Gateway whether the current request should be rejected.

If an expression evalueates to true, Project X API Gateway will reject the request.

It's useful for implementing premium features and impose limitations on input parameters.

Example

For instance, a limitation might sound as

For the "Basic" subscription plan request body can't exceed a maximum of 1000 bytes.

In this case, the Project X API Gateway needs to check the request body length and reject the request if the length exceeds 1000 bytes.

The expression needs to be:

request.body.length > 1000

One rejection rule can be applied to several endpoints. The expression will be evaluated for each call to any of the selected endpoints and if the result is true, the call is rejected.

Add rejection rule

  1. Click "Add rejection rule".

  2. Enter the expression, select the endpoints this rule applies to, and click "Save".

  3. The rejection rule is now added to the product.

Expression variables

There is a number of variables that can be used in the expression.

Note that response variables are not available, since rejection rules are evaluated before proxying the request.


Path parameters

path.params.* — placeholder values specified in the endpoint URL.

Note

Placeholder names are case-sensitive.

Example

If an endpoint URL is /resource/{resourceId}

and the HTTP request URL is /resource/801d49c2-ca05-42b1-97af-baf0ddf36ba3,

then there will be a variable path.params.resourceId with value "801d49c2-ca05-42b1-97af-baf0ddf36ba3".

path.params.resourceId // "801d49c2-ca05-42b1-97af-baf0ddf36ba3"

Client IP address

request.remote_addr — Client IP address.


Request headers

request.headers['header-name'] — Request header values.

Warning

Header names are lower-case.

Example

request.headers['content-type'] == 'application/json'

Request query string parameters

request.query['query_string_parameter_name'] — Request query string parameters.

Warning

Query string parameter names are case-sensitive.

Example
request.query['page'] > 100

Request body

request.body — Request body.

Example
request.body.length > 1000