> ## Documentation Index
> Fetch the complete documentation index at: https://unkey.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Apply rate limiting

> Check and enforce rate limits for any identifier (user ID, IP address, API client, etc.).

Use this for rate limiting beyond API keys - limit users by ID, IPs by address, or any custom identifier. Supports namespace organization, variable costs, and custom overrides.

**Response Codes**: Rate limit checks return HTTP 200 regardless of whether the limit is exceeded — check the `success` field in the response to determine if the request should be allowed. A 429 may be returned if the workspace exceeds its API rate limit. Other 4xx responses indicate auth, namespace existence/deletion, or validation errors (e.g., 410 Gone for deleted namespaces). 5xx responses indicate server errors.

**Required Permissions**

Your root key must have one of the following permissions:
- `ratelimit.*.limit` (to check limits in any namespace)
- `ratelimit.<namespace_id>.limit` (to check limits in a specific namespace)




## OpenAPI

````yaml https://spec.speakeasy.com/unkey/unkey/openapi-json-with-code-samples post /v2/ratelimit.limit
openapi: 3.1.0
info:
  description: >-
    Unkey's API provides programmatic access for all resources within our
    platform.



    ### Authentication

    #

    This API uses HTTP Bearer authentication with root keys. Most endpoints
    require specific permissions associated with your root key. When making
    requests, include your root key in the `Authorization` header:

    ```

    Authorization: Bearer unkey_xxxxxxxxxxx

    ```


    All responses follow a consistent envelope structure that separates
    operational metadata from actual data. This design provides several
    benefits:

    - Debugging: Every response includes a unique requestId for tracing issues

    - Consistency: Predictable response format across all endpoints

    - Extensibility: Easy to add new metadata without breaking existing
    integrations

    - Error Handling: Unified error format with actionable information


    ### Success Response Format:

    ```json

    {
      "meta": {
        "requestId": "req_123456"
      },
      "data": {
        // Actual response data here
      }
    }

    ```


    The meta object contains operational information:

    - `requestId`: Unique identifier for this request (essential for support)


    The data object contains the actual response data specific to each endpoint.


    ### Paginated Response Format:

    ```json

    {
      "meta": {
        "requestId": "req_123456"
      },
      "data": [
        // Array of results
      ],
      "pagination": {
        "cursor": "next_page_token",
        "hasMore": true
      }
    }

    ```


    The pagination object appears on list endpoints and contains:

    - `cursor`: Token for requesting the next page

    - `hasMore`: Whether more results are available


    ### Error Response Format:

    ```json

    {
      "meta": {
        "requestId": "req_2c9a0jf23l4k567"
      },
      "error": {
        "detail": "The resource you are attempting to modify is protected and cannot be changed",
        "status": 403,
        "title": "Forbidden",
        "type": "https://unkey.com/docs/errors/unkey/application/protected_resource"
      }
    }

    ```


    Error responses include comprehensive diagnostic information:

    - `title`: Human-readable error summary

    - `detail`: Specific description of what went wrong

    - `status`: HTTP status code

    - `type`: Link to error documentation

    - `errors`: Array of validation errors (for 400 responses)


    This structure ensures you always have the context needed to debug issues
    and take corrective action.
  title: Unkey API
  version: 2.0.0
servers:
  - url: https://api.unkey.com
security:
  - rootKey: []
tags:
  - description: Analytics query operations
    name: analytics
  - description: API management operations
    name: apis
  - description: Deployment operations
    name: deploy
  - description: Identity management operations
    name: identities
  - description: API key management operations
    name: keys
  - description: Health check operations
    name: liveness
  - description: Permission and role management operations
    name: permissions
  - description: Customer Portal session management
    name: portal
  - description: Rate limiting operations
    name: ratelimit
paths:
  /v2/ratelimit.limit:
    post:
      tags:
        - ratelimit
      summary: Apply rate limiting
      description: >
        Check and enforce rate limits for any identifier (user ID, IP address,
        API client, etc.).


        Use this for rate limiting beyond API keys - limit users by ID, IPs by
        address, or any custom identifier. Supports namespace organization,
        variable costs, and custom overrides.


        **Response Codes**: Rate limit checks return HTTP 200 regardless of
        whether the limit is exceeded — check the `success` field in the
        response to determine if the request should be allowed. A 429 may be
        returned if the workspace exceeds its API rate limit. Other 4xx
        responses indicate auth, namespace existence/deletion, or validation
        errors (e.g., 410 Gone for deleted namespaces). 5xx responses indicate
        server errors.


        **Required Permissions**


        Your root key must have one of the following permissions:

        - `ratelimit.*.limit` (to check limits in any namespace)

        - `ratelimit.<namespace_id>.limit` (to check limits in a specific
        namespace)
      operationId: ratelimit.limit
      requestBody:
        content:
          application/json:
            examples:
              basic:
                summary: Basic rate limit check
                value:
                  duration: 60000
                  identifier: user_abc123
                  limit: 100
                  namespace: api.requests
              ipLimit:
                summary: IP-based rate limiting
                value:
                  duration: 60000
                  identifier: 203.0.113.42
                  limit: 5
                  namespace: auth.login
              weightedCost:
                summary: Operation with variable cost
                value:
                  cost: 5
                  duration: 3600000
                  identifier: user_def456
                  limit: 50
                  namespace: api.heavy_operations
            schema:
              $ref: '#/components/schemas/V2RatelimitLimitRequestBody'
        required: true
      responses:
        '200':
          content:
            application/json:
              examples:
                allowed:
                  summary: Request allowed
                  value:
                    data:
                      limit: 100
                      remaining: 99
                      reset: 1714582980000
                      success: true
                    meta:
                      requestId: req_01H9TQPP77V5E48E9SH0BG0ZQX
                limitReached:
                  summary: Rate limit exceeded
                  value:
                    data:
                      limit: 100
                      remaining: 0
                      reset: 1714582980000
                      success: false
                    meta:
                      requestId: req_01H9TQPP77V5E48E9SH0BG0ZQY
                withOverride:
                  summary: With custom override applied
                  value:
                    data:
                      limit: 1000
                      overrideId: ovr_2cGKbMxRyIzhCxo1Idjz8q
                      remaining: 995
                      reset: 1714582980000
                      success: true
                    meta:
                      requestId: req_01H9TQPP77V5E48E9SH0BG0ZQZ
              schema:
                $ref: '#/components/schemas/V2RatelimitLimitResponseBody'
          description: >
            Rate limit check completed successfully. Check the `success` field
            to determine if the request is allowed.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestErrorResponse'
          description: Bad request
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedErrorResponse'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenErrorResponse'
          description: Forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFoundErrorResponse'
          description: Not Found
        '410':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GoneErrorResponse'
          description: Gone - Namespace has been deleted
        '429':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/TooManyRequestsErrorResponse'
          description: Too Many Requests
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalServerErrorResponse'
          description: Internal server error
      security:
        - rootKey: []
      x-codeSamples:
        - lang: go
          label: Go (SDK)
          source: "package main\n\nimport(\n\t\"context\"\n\t\"os\"\n\tunkey \"github.com/unkeyed/sdks/api/go/v2\"\n\t\"github.com/unkeyed/sdks/api/go/v2/models/components\"\n\t\"log\"\n)\n\nfunc main() {\n    ctx := context.Background()\n\n    s := unkey.New(\n        unkey.WithSecurity(os.Getenv(\"UNKEY_ROOT_KEY\")),\n    )\n\n    res, err := s.Ratelimit.Limit(ctx, components.V2RatelimitLimitRequestBody{\n        Namespace: \"api.requests\",\n        Cost: unkey.Pointer[int64](5),\n        Duration: 60000,\n        Identifier: \"user_abc123\",\n        Limit: 100,\n    })\n    if err != nil {\n        log.Fatal(err)\n    }\n    if res.V2RatelimitLimitResponseBody != nil {\n        // handle response\n    }\n}"
        - lang: python
          label: Python (SDK)
          source: |-
            from unkey.py import Unkey


            with Unkey(
                root_key="<YOUR_BEARER_TOKEN_HERE>",
            ) as unkey:

                res = unkey.ratelimit.limit(namespace="api.requests", duration=60000, identifier="user_abc123", limit=100, cost=5)

                # Handle response
                print(res)
        - lang: typescript
          label: Typescript (SDK)
          source: |-
            import { Unkey } from "@unkey/api";

            const unkey = new Unkey({
              rootKey: process.env["UNKEY_ROOT_KEY"] ?? "",
            });

            async function run() {
              const result = await unkey.ratelimit.limit({
                namespace: "api.requests",
                cost: 5,
                duration: 60000,
                identifier: "user_abc123",
                limit: 100,
              });

              console.log(result);
            }

            run();
components:
  schemas:
    V2RatelimitLimitRequestBody:
      additionalProperties: false
      properties:
        namespace:
          type: string
          minLength: 1
          maxLength: 255
          description: The id or name of the namespace.
          example: sms.sign_up
        cost:
          type: integer
          format: int64
          minimum: 0
          default: 1
          description: >
            Sets how much of the rate limit quota this request consumes,
            enabling weighted rate limiting.

            Use higher values for resource-intensive operations and 0 for
            tracking without limiting.

            When accumulated cost exceeds the limit within the duration window,
            subsequent requests are rejected.

            Essential for implementing fair usage policies and preventing
            resource abuse through expensive operations.
          example: 5
        duration:
          type: integer
          format: int64
          minimum: 1000
          maximum: 2592000000
          description: >
            Sets the rate limit window duration in milliseconds after which the
            counter resets.

            Shorter durations enable faster recovery but may be less effective
            against sustained abuse.

            Common values include 60000 (1 minute), 3600000 (1 hour), and
            86400000 (24 hours).

            Balance user experience with protection needs when choosing window
            sizes.
          example: 60000
        identifier:
          type: string
          minLength: 1
          maxLength: 255
          description: >
            Defines the scope of rate limiting by identifying the entity being
            limited.

            Use user IDs for per-user limits, IP addresses for anonymous
            limiting, or API key IDs for per-key limits.

            Accepts letters, numbers, underscores, dots, colons, slashes, and
            hyphens for flexible identifier formats.

            The same identifier can be used across different namespaces to apply
            multiple rate limit types.

            Choose identifiers that provide appropriate granularity for your
            rate limiting strategy.
          example: user_12345
        limit:
          type: integer
          format: int64
          minimum: 1
          description: >
            Sets the maximum operations allowed within the duration window
            before requests are rejected.

            When this limit is reached, subsequent requests fail with
            `RATE_LIMITED` until the window resets.

            Balance user experience with resource protection when setting limits
            for different user tiers.

            Consider system capacity, business requirements, and fair usage
            policies in limit determination.
          example: 1000
      required:
        - namespace
        - identifier
        - limit
        - duration
      type: object
    V2RatelimitLimitResponseBody:
      type: object
      required:
        - meta
        - data
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        data:
          $ref: '#/components/schemas/V2RatelimitLimitResponseData'
    BadRequestErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BadRequestErrorDetails'
      description: >-
        Error response for invalid requests that cannot be processed due to
        client-side errors. This typically occurs when request parameters are
        missing, malformed, or fail validation rules. The response includes
        detailed information about the specific errors in the request, including
        the location of each error and suggestions for fixing it. When receiving
        this error, check the 'errors' array in the response for specific
        validation issues that need to be addressed before retrying.
    UnauthorizedErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when authentication has failed or credentials are
        missing. This occurs when:

        - No authentication token is provided in the request

        - The provided token is invalid, expired, or malformed

        - The token format doesn't match expected patterns


        To resolve this error, ensure you're including a valid root key in the
        Authorization header.
    ForbiddenErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when the provided credentials are valid but lack
        sufficient permissions for the requested operation. This occurs when:

        - The root key doesn't have the required permissions for this endpoint

        - The operation requires elevated privileges that the current key lacks

        - Access to the requested resource is restricted based on workspace
        settings


        To resolve this error, ensure your root key has the necessary
        permissions or contact your workspace administrator.
    NotFoundErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when the requested resource cannot be found. This occurs
        when:

        - The specified resource ID doesn't exist in your workspace

        - The resource has been deleted or moved

        - The resource exists but is not accessible with current permissions


        To resolve this error, verify the resource ID is correct and that you
        have access to it.
    GoneErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when the requested resource has been soft-deleted and is
        no longer available. This occurs when:

        - The resource has been marked as deleted but still exists in the
        database

        - The resource is intentionally unavailable but could potentially be
        restored

        - The resource cannot be restored through the API or dashboard


        To resolve this error, contact support if you need the resource
        restored.
    TooManyRequestsErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when the client has sent too many requests in a given
        time period. This occurs when you've exceeded a rate limit or quota for
        the resource you're accessing.


        The rate limit resets automatically after the time window expires. To
        avoid this error:

        - Implement exponential backoff when retrying requests

        - Cache results where appropriate to reduce request frequency

        - Check the error detail message for specific quota information

        - Contact support if you need a higher quota for your use case
    InternalServerErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when an unexpected error occurs on the server. This
        indicates a problem with Unkey's systems rather than your request.


        When you encounter this error:

        - The request ID in the response can help Unkey support investigate the
        issue

        - The error is likely temporary and retrying may succeed

        - If the error persists, contact Unkey support with the request ID
    Meta:
      type: object
      required:
        - requestId
      properties:
        requestId:
          description: >-
            A unique id for this request. Always include this ID when contacting
            support about a specific API request. This identifier allows Unkey's
            support team to trace the exact request through logs and diagnostic
            systems to provide faster assistance.
          example: req_123
          type: string
      additionalProperties: false
      description: >-
        Metadata object included in every API response. This provides context
        about the request and is essential for debugging, audit trails, and
        support inquiries. The `requestId` is particularly important when
        troubleshooting issues with the Unkey support team.
    V2RatelimitLimitResponseData:
      type: object
      properties:
        limit:
          description: >-
            The maximum number of operations allowed within the time window.
            This reflects either the default limit specified in the request or
            an override limit if one exists for this identifier.


            This value helps clients understand their total quota for the
            current window.
          format: int64
          type: integer
        remaining:
          description: >-
            The number of operations remaining in the current window before the
            rate limit is exceeded. Applications should use this value to:


            - Implement client-side throttling before hitting limits

            - Display usage information to end users

            - Trigger alerts when approaching limits

            - Adjust request patterns based on available capacity


            When this reaches zero, requests will be rejected until the window
            resets.
          format: int64
          type: integer
        reset:
          description: >-
            The Unix timestamp in milliseconds when the rate limit window will
            reset and 'remaining' will return to 'limit'.


            This timestamp enables clients to:

            - Calculate and display wait times to users

            - Implement intelligent retry mechanisms

            - Schedule requests to resume after the reset

            - Implement exponential backoff when needed


            The reset time is based on a sliding window from the first request
            in the current window.
          format: int64
          type: integer
        success:
          description: >-
            Whether the request passed the rate limit check. If true, the
            request is allowed to proceed. If false, the request has exceeded
            the rate limit and should be blocked or rejected.


            You MUST check this field to determine if the request should
            proceed, as the endpoint always returns `HTTP 200` even when rate
            limited.
          type: boolean
        overrideId:
          description: >-
            If a rate limit override was applied for this identifier, this field
            contains the ID of the override that was used. Empty when no
            override is in effect.


            This can be useful for:

            - Debugging which override rule was matched

            - Tracking the effects of specific overrides

            - Understanding why limits differ from default values
          type: string
          x-go-type-skip-optional-pointer: true
          x-go-type-skip-optional-pointer-with-omitzero: true
      required:
        - limit
        - remaining
        - reset
        - success
    BadRequestErrorDetails:
      allOf:
        - $ref: '#/components/schemas/BaseError'
        - type: object
          properties:
            errors:
              description: >-
                List of individual validation errors that occurred in the
                request. Each error provides specific details about what failed
                validation, where the error occurred in the request, and
                suggestions for fixing it. This granular information helps
                developers quickly identify and resolve multiple issues in a
                single request without having to make repeated API calls.
              items:
                $ref: '#/components/schemas/ValidationError'
              type: array
          required:
            - errors
      description: >-
        Extended error details specifically for bad request (400) errors. This
        builds on the BaseError structure by adding an array of individual
        validation errors, making it easy to identify and fix multiple issues at
        once.
    BaseError:
      properties:
        detail:
          description: >-
            A human-readable explanation specific to this occurrence of the
            problem. This provides detailed information about what went wrong
            and potential remediation steps. The message is intended to be
            helpful for developers troubleshooting the issue.
          example: Property foo is required but is missing.
          type: string
        status:
          description: >-
            HTTP status code that corresponds to this error. This will match the
            status code in the HTTP response. Common codes include `400` (Bad
            Request), `401` (Unauthorized), `403` (Forbidden), `404` (Not
            Found), `409` (Conflict), and `500` (Internal Server Error).
          example: 404
          format: int
          type: integer
        title:
          description: >-
            A short, human-readable summary of the problem type. This remains
            constant from occurrence to occurrence of the same problem and
            should be used for programmatic handling.
          example: Not Found
          type: string
        type:
          description: >-
            A URI reference that identifies the problem type. This provides a
            stable identifier for the error that can be used for documentation
            lookups and programmatic error handling. When followed, this URI
            should provide human-readable documentation for the problem type.
          example: https://unkey.com/docs/errors/unkey/resource/not_found
          type: string
      required:
        - title
        - detail
        - status
        - type
      type: object
      additionalProperties: false
      description: >-
        Base error structure following Problem Details for HTTP APIs (RFC 7807).
        This provides a standardized way to carry machine-readable details of
        errors in HTTP response content.
    ValidationError:
      additionalProperties: false
      properties:
        location:
          description: >-
            JSON path indicating exactly where in the request the error
            occurred. This helps pinpoint the problematic field or parameter.
            Examples include:

            - 'body.name' (field in request body)

            - 'body.items[3].tags' (nested array element)

            - 'path.apiId' (path parameter)

            - 'query.limit' (query parameter)

            Use this location to identify exactly which part of your request
            needs correction.
          type: string
          example: body.permissions[0].name
        message:
          description: >-
            Detailed error message explaining what validation rule was violated.
            This provides specific information about why the field or parameter
            was rejected, such as format errors, invalid values, or constraint
            violations.
          type: string
          example: Must be at least 3 characters long
        fix:
          description: >-
            A human-readable suggestion describing how to fix the error. This
            provides practical guidance on what changes would satisfy the
            validation requirements. Not all validation errors include fix
            suggestions, but when present, they offer specific remediation
            advice.
          type: string
          example: >-
            Ensure the name uses only alphanumeric characters, underscores, and
            hyphens
      required:
        - location
        - message
      type: object
      description: >-
        Individual validation error details. Each validation error provides
        precise information about what failed, where it failed, and how to fix
        it, enabling efficient error resolution.
  securitySchemes:
    rootKey:
      bearerFormat: root key
      description: >-
        Unkey uses API keys (root keys) for authentication. These keys authorize
        access to management operations in the API.

        To authenticate, include your root key in the Authorization header of
        each request:

        ```

        Authorization: Bearer unkey_123

        ```

        Root keys have specific permissions attached to them, controlling what
        operations they can perform. Key permissions follow a hierarchical
        structure with patterns like `resource.resource_id.action` (e.g.,
        `apis.*.create_key`, `apis.*.read_api`).

        Security best practices:

        - Keep root keys secure and never expose them in client-side code

        - Use different root keys for different environments

        - Rotate keys periodically, especially after team member departures

        - Create keys with minimal necessary permissions following least
        privilege principle

        - Monitor key usage with audit logs.
      scheme: bearer
      type: http

````