# Rate limits

> How many requests you can make, when limits reset, and what to do when you hit one.

Source: https://dev.virlo.ai/docs/rate-limits
Markdown: https://dev.virlo.ai/docs/rate-limits.md
Section: How the API works

## About the Virlo API (applies to every page)

- Base URL: `https://api.virlo.ai/v1`. Every request needs the header `Authorization: Bearer YOUR_API_KEY` (keys start with `virlo_tkn_`).
- Responses are JSON inside a `data` field, except the `/v1/webhooks` endpoints, which return the object or array directly. Field names are snake_case.
- Prices are in US dollars from a prepaid balance. 1 credit = $0.01. The `X-Cost` response header on each successful response is the exact charge. Errors are free.
- Slow jobs return an ID. Check its status every 15 seconds (or whatever `retry_after_seconds` says) until `finalized` is `true`.
- All docs pages: https://dev.virlo.ai/llms.txt. Every page in one file: https://dev.virlo.ai/llms-full.txt. MCP server for AI assistants: https://dev.virlo.ai/api/mcp/mcp.

---

Rate limits cap how often your key can call each endpoint (one API address, like `/v1/trends`) per minute, hour, or day. Most accounts never reach them.

**At a glance**

- **What it does:** Caps requests per API key, separately for each endpoint.
- **You get back:** Responses show your requests left. Over a limit, a `429` error says how long to wait.
- **Cost:** Free. Blocked requests are not charged.
- **Normal limit:** 10,000 requests per day for each endpoint. A few have tighter limits.
- **When it resets:** At fixed UTC times, not rolling: each new minute, each hour on the hour, and midnight UTC.

## How rate limits work

- **Per key and per endpoint.** Each endpoint gets its own 10,000 per day, not a shared total. Different creators or hashtags share that endpoint's limit.
- **Reading and creating share a limit.** `GET /v1/webhooks` and `POST /v1/webhooks` count as one. Only the old agent endpoints (Legacy in the sidebar) count them apart.
- **What counts.** Most requests count and get limit headers, even bad-input errors (`400`). A bad key (`401`) and most low-balance errors (`402`) don't count and get none.
- **No valid key.** If the key is missing or doesn't start with `virlo_tkn_`, your IP address gets about 20 quick tries, then about 1 per second. Faster requests get a `429` with code `too_many_requests`.

## Response headers

- `X-RateLimit-Limit` (integer, optional): Requests allowed in the current window (a minute, hour, or day).
- `X-RateLimit-Remaining` (integer, optional): Requests left in that window.
- `X-RateLimit-Reset` (integer, optional): When that window resets, as a Unix timestamp (`1790294400` is midnight UTC, September 25, 2026).
- `Retry-After` (integer, optional): Only on a `429` from your key's limit: seconds to wait before retrying.

> **Note:** When an endpoint has minute, hour, and day limits, the headers show only the one closest to running out. `GET /v1/hashtags` can report `50` (per minute) on one call and `500` (per hour) on the next.

## Default rate limits

Every standard API key gets these. If your account has custom limits, the headers show yours.

| Feature | Endpoints | Per minute | Per hour | Per day |
| - | - | - | - | - |
| Creator lookup | `GET /v1/satellite/creator/:platform/:username` | 5 | 100 | 1,000 |
| Video outlier check | `POST /v1/satellite/video-outlier` | 5 | 100 | 1,000 |
| [Hashtag stats](https://dev.virlo.ai/docs/hashtags) | `GET /v1/hashtags`, `GET /v1/hashtags/:hashtag/performance`, `GET /v1/tiktok/hashtags`, `GET /v1/youtube/hashtags`, `GET /v1/instagram/hashtags` | 50 | 500 | 5,000 |
| Video digests | `GET /v1/videos/digest`, `GET /v1/tiktok/videos/digest`, `GET /v1/youtube/videos/digest`, `GET /v1/instagram/videos/digest` | 50 | 500 | 5,000 |
| Trends | `GET /v1/trends`, `GET /v1/trends/digest` | 50 | 500 | 5,000 |
| Emerging trends | `GET /v1/trends/emerging` | 60 | 600 | 6,000 |
| Everything else, including `/v1/satellite/hashtags` and `/v1/satellite/sounds` | All others | No cap | No cap | 10,000 |

Each endpoint in a row has its own counter.

- **[Batch creator lookup](https://dev.virlo.ai/docs/satellite#batch-creator-lookup)** (`POST /v1/satellite/creators/batch`) takes up to 25 creators per call and uses the 10,000-per-day limit, not the 5-per-minute one. Each creator costs $0.50, or up to $1.00 with audience data, unless the 6-hour cache answers it for free.
- **Lookup status checks** also use the 10,000-per-day limit. Check every 15 seconds, or whatever `retry_after_seconds` says.
- **Old agent endpoints** go as low as 2 per minute. Their replacement, `POST /v1/agents`, has the normal limit.

## Handling rate limits

When you get a `429`:

1. Check the [`code`](https://dev.virlo.ai/docs/errors). `rate_limit_exceeded`: you hit a limit, so wait. `too_many_requests`: fix your missing or mistyped key.
2. Wait the seconds in `Retry-After` (or `retry_after` in the body), then retry.
3. No wait time given? Wait a few seconds, doubling after each failed try.

To avoid more, pace to the limit: 5 per minute is one request every 12 seconds; 50 per minute, one every 1.2 seconds.

**429 response:**

```json
{
  "statusCode": 429,
  "code": "rate_limit_exceeded",
  "message": "Rate limit exceeded",
  "error": "Too Many Requests",
  "limit": 5,
  "remaining": 0,
  "reset_at": 1790270580,
  "reset_at_formatted": "September 24th, 2026, 5:23 PM UTC",
  "retry_after": 42
}
```

> **Note:** The body also repeats `resetAt`, `resetAtFormatted`, and `retryAfter`. These older names will be removed, so read the ones above.

## Need higher limits?

Email <info@virlo.ai> or [book a call](https://cal.com/virlo-support).

---

More in How the API works:

- [How results load](https://dev.virlo.ai/docs/async-data.md)
- [Pagination](https://dev.virlo.ai/docs/pagination.md)
- [Webhooks](https://dev.virlo.ai/docs/webhooks.md)
- [Errors](https://dev.virlo.ai/docs/errors.md)
- [Workflow recipes](https://dev.virlo.ai/docs/recipes.md)
- [API playground](https://dev.virlo.ai/docs/playground.md)
