Skip to main content
Signa enforces rate limits to ensure platform stability and fair usage across all customers. Limits are applied per organization.

Limits

CategoryLimitEndpoints
Reads (tier-1)10,000/minAll GET/HEAD/OPTIONS requests not listed below
Search (tier-2)10,000/minPOST /v1/trademarks, GET /v1/trademarks, GET /v1/suggest
Writes (tier-3)1,000/minAll POST, PATCH, DELETE requests not listed below
MCP1,000/minAll /mcp endpoints
Note that POST /v1/trademarks (the search endpoint) counts as a write because it uses the POST method. GET /v1/trademarks counts as a read.
Rate limits are counted per organization. All API keys under the same org share a single rate limit window.

Rate Limit Headers

Every API response includes IETF-standard rate limit headers so you can monitor your usage in real time:
HTTP/1.1 200 OK
RateLimit-Policy: 10000;w=60
RateLimit: remaining=9994, reset=30
HeaderFormatDescription
RateLimit-Policy{limit};w={windowSec}The limit and window size in seconds (e.g., 1000;w=60 means 1,000 requests per 60-second window).
RateLimitremaining={N}, reset={seconds}Remaining requests in the current window and seconds until the window resets.
Retry-After{seconds}Only present on 429 responses. Number of seconds to wait before retrying.
Monitor the remaining value from the RateLimit header proactively. If it drops below 10% of your limit, consider slowing down requests rather than hitting 429 errors.

Per-Endpoint Rate Information

Each endpoint falls into the tier determined by its HTTP method and path, as described above. Some notable classifications:
EndpointTierLimitNotes
GET /v1/trademarksReads10,000/minGET falls into the reads tier.
POST /v1/trademarksWrites1,000/minPOST method falls into the writes tier.
GET /v1/trademarks/suggestSearch10,000/minExplicitly routed to the search tier.
GET /v1/suggestSearch10,000/minExplicitly routed to the search tier.
POST /v1/trademarks/batchWrites1,000/minEach batch request counts as 1, regardless of batch size.

Handling 429 Responses

When you exceed your rate limit, the API returns a 429 Too Many Requests status with details about when you can retry:
HTTP/1.1 429 Too Many Requests
RateLimit-Policy: 10000;w=60
RateLimit: remaining=0, reset=12
Retry-After: 12
{
  "error": {
    "type": "https://api.signa.so/errors/rate_limited",
    "title": "Rate limit exceeded",
    "status": 429,
    "detail": "Rate limit exceeded. Retry after 12 seconds.",
    "retryable": true,
    "retry_after": 12
  },
  "request_id": "req_abc123"
}
The Retry-After response header and the retry_after field in the body both contain the number of seconds to wait.
Ignoring 429 responses and continuing to send requests will not help — those requests are also rejected. In extreme cases, sustained limit violations may result in a temporary block of your API key.

Exponential Backoff

When you receive a 429, wait for the Retry-After duration and then retry with exponential backoff:
async function fetchWithRateLimitRetry(
  url: string,
  options: RequestInit,
  maxRetries = 3
): Promise<Response> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) {
      return response;
    }

    if (attempt === maxRetries) {
      return response; // Return the 429 after exhausting retries
    }

    // Use Retry-After header, with exponential backoff as fallback
    const retryAfter = parseInt(
      response.headers.get('Retry-After') ?? '1',
      10
    );
    const delay = retryAfter * 1000 + Math.random() * 1000;

    await new Promise((resolve) => setTimeout(resolve, delay));
  }

  throw new Error('Unreachable');
}
The Signa TypeScript SDK handles 429 responses automatically with built-in retry logic. If you are using the SDK, you do not need to implement this yourself.

Monitoring Usage

GET /v1/usage

Check your current rate limit status and historical usage without making a full API call:
GET /v1/usage
Authorization: Bearer sig_live_YOUR_KEY
{
  "object": "usage",
  "current_period": {
    "reads": { "used": 4521, "limit": 100000, "resets_at": "2026-03-25T00:00:00Z" },
    "search": { "used": 892, "limit": 100000, "resets_at": "2026-03-25T00:00:00Z" },
    "writes": { "used": 34, "limit": 100000, "resets_at": "2026-03-25T00:00:00Z" }
  },
  "rate_limits": {
    "reads": { "remaining": 9994, "limit": 10000, "resets_in": 30 },
    "search": { "remaining": 9998, "limit": 10000, "resets_in": 30 },
    "writes": { "remaining": 999, "limit": 1000, "resets_in": 30 }
  },
  "request_id": "req_abc123"
}
current_period tracks daily usage against your daily cap. rate_limits shows the current sliding-window status for each category.
Avoid polling the /v1/usage endpoint in a tight loop. It shares the standard reads quota.

Best Practices

A single batch request of 100 IDs counts as 1 request against your rate limit, compared to 100 individual GET requests. See the batch operations guide for details.
Using If-None-Match headers with ETags avoids downloading unchanged response bodies, saving bandwidth and processing time. While 304 Not Modified responses still count against your rate limit, they are significantly cheaper for both client and server. See the caching guide for implementation patterns.
If you are periodically checking for trademark status changes, use Trademark History on specific marks rather than re-running broad searches. A targeted lookup costs 1 read request and avoids burning your search quota.
Bursting 500 requests in the first second of a window is more likely to trigger rate limiting than spreading them evenly across the minute. If you need to process a large batch, add a small delay (50—100ms) between requests.
If your application has both a user-facing dashboard and a background sync job, create separate API keys for each. This prevents a background job from exhausting the rate limit that your dashboard users depend on.
Build alerting around the remaining value in the RateLimit header. If it consistently drops below 20% of your limit, you may need to optimize your request patterns or contact us about higher limits.

Need Higher Limits?

If you are consistently hitting rate limits:
  1. Optimize: Apply the best practices above (caching, batching, watches).
  2. Contact us: Reach out at support@signa.so to discuss higher limits tailored to your workload.