API Rate Limiting
Waqti limits how many API requests each tenant can make in a sliding time window. Limits protect platform stability and ensure fair usage across customers.
Overview
Rate limiting applies per API token (and therefore per tenant context). When you send a request, it counts toward:
- Per-minute burst — how many requests you can make within a short window.
- Per-day quota — total requests allowed per calendar day (UTC), except on Enterprise where daily volume is not capped.
If either limit is exceeded, the API responds with 429 Too Many Requests. Successful responses include headers so you can throttle clients before hitting the limit.
Base URL (same as the main API reference):
https://api.waqti.sa/v1Rate limits by plan
Limits depend on your subscription. Higher tiers allow more throughput for integrations, reporting, and automation.
| Plan | Requests / minute | Requests / day |
|---|---|---|
| Basic | 60 | 1,000 |
| Professional | 300 | 10,000 |
| Enterprise | 1,000 | Unlimited |
Plan changes
If you upgrade or downgrade, new limits apply on the next request after the billing plan update propagates (typically within a few minutes).
Response headers
Every API response includes standard rate limit headers so clients can slow down proactively.
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current per-minute window for your plan. |
X-RateLimit-Remaining | Approximate number of requests left in the current per-minute window. |
X-RateLimit-Reset | Unix timestamp (seconds) when the per-minute window resets. |
Example (successful response):
HTTP/1.1 200 OK
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 297
X-RateLimit-Reset: 1705312260
Content-Type: application/jsonWhen the per-minute limit is hit, X-RateLimit-Remaining is 0 and Retry-After may indicate how many seconds to wait before retrying (see below).
429 Too Many Requests
When you exceed the per-minute or per-day limit, the API returns 429 with a JSON body and helpful headers.
Example response
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705312305
Content-Type: application/json{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please retry after 45 seconds."
},
"meta": {
"timestamp": "2025-01-15T10:31:45Z",
"request_id": "req_rl_9f3a2b1c"
}
}| Header / field | Purpose |
|---|---|
Retry-After | Seconds to wait before retrying (per-minute window). |
X-RateLimit-Reset | When the minute window resets (Unix seconds). |
error.code | Machine-readable reason (RATE_LIMIT_EXCEEDED). |
Example request that might trigger 429
curl -i -X GET "https://api.waqti.sa/v1/purchase-orders" \
-H "Authorization: Bearer 3|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0" \
-H "Accept: application/json"If limited, the response status is 429 and the body explains the condition. For daily quota exhaustion, the message will reflect the daily cap; use X-RateLimit-Reset (when present) or the error details to know when the next UTC day begins.
Best practices
Exponential backoff
On 429, do not retry immediately in a tight loop. Use exponential backoff with jitter:
- Read
Retry-After(seconds) when present and sleep at least that long. - Otherwise, start with a short delay (e.g. 1s), double on repeated 429s, and cap (e.g. 60s).
- Add random jitter so many workers do not retry at the same instant.
Caching
- Cache stable reference data (vendors, departments, configuration) where your integration allows.
- Use conditional requests or ETag /
If-None-Matchwhen the API supports them to avoid re-downloading unchanged resources. - Prefer single list calls with filters (
search,status, date ranges) over many small detail calls when syncing.
Batch-oriented workflows
- Prefer pagination with a sensible
per_page(up to the documented maximum) instead of hammering the API with tiny pages. - Serialize write operations that depend on each other; parallel writes multiply load and failure modes.
- Schedule heavy reporting or backfills during off-peak hours when possible.
Read vs write endpoints
The same per-minute and per-day quotas apply to all authenticated API traffic. What differs is how you should use read vs write endpoints:
| Category | HTTP methods | Typical endpoints | Integration notes |
|---|---|---|---|
| Read | GET (and HEAD where supported) | List and show resources (/purchase-orders, /vendors/{id}, …) | Safe to retry; ideal for caching and pagination. |
| Write | POST, PUT, PATCH, DELETE | Create/update/delete, submit for approval, etc. | Use idempotency keys where offered; avoid duplicate submits on retry after timeouts. |
Counting: one HTTP request counts as one toward your limits, whether it is a read or a write. Writes often trigger more downstream work (validation, workflows), so keep write bursts lower than theoretical read bursts even when the numeric limit is the same.