Skip to main content

Overview

The API enforces rate limits using Laravel’s named throttle middleware groups. Different endpoint categories use different throttle configurations to balance protection and usability.

Throttle groups

GroupApplied toBehavior
throttle:apiGeneral API endpoints (default)Standard per-IP/user limit
throttle:api.otp-generationPOST /api/v1/otp/generateStrict — prevents OTP flooding
throttle:api.verificationPOST /api/v1/otp/verify, coupon verify, validate couponStrict — prevents brute-force
throttle:api.transactionsPOST /api/v1/orders (public checkout)Per-IP transaction rate limit
throttle:tenant-awarePOST /api/v1/interactionsTenant-scoped analytics protection

throttle:api — general

Applied by default to most public and authenticated endpoints. Uses Laravel’s standard rate limiter configured in App\Providers\RouteServiceProvider.

throttle:api.otp-generation — OTP generation

Applied only to POST /api/v1/otp/generate. This route also uses the idempotency middleware to prevent duplicate OTP requests within the same time window.

throttle:api.verification — OTP verification

Applied to POST /api/v1/otp/verify, POST /api/v1/coupons/verify, and POST /api/v1/checkout/validate-coupon. Protects against code enumeration attacks.

throttle:tenant-aware — tenant-aware analytics

Applied to POST /api/v1/interactions. Replaced the former analytics-protection group. Throttling is scoped per tenant to prevent a single tenant’s traffic from affecting others.

AI budget throttling

The POST /api/v1/ai/generate endpoint uses an additional token bucket rate limiter on top of the route-level throttle. Each authenticated user is allowed 5 AI generation requests per hour. This is enforced at the controller level with a dedicated limiter key (ai-gen:{user_id}).

Handling 429 responses

When you exceed a rate limit the API returns 429 Too Many Requests.
{
  "message": "Too Many Attempts."
}
For the AI endpoint the response includes a retry hint:
{
  "message": "Límite de generación excedido. Intenta de nuevo en 45:00 minutos."
}
Check the standard Laravel throttle response headers to determine when to retry:
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the window
X-RateLimit-RemainingRequests remaining in the current window
Retry-AfterSeconds until the limit resets
Repeated rate-limit violations from the same IP may trigger additional protections at the infrastructure level.

Build docs developers (and LLMs) love