Getting Started
Authentication, common parameters, and best practices for the Rybbit Stats API
The API is currently in beta. There may be breaking changes as we continue to improve and expand the API.
API Playground
The easiest way to explore and test the API is using the built-in API Playground in your Rybbit dashboard. Access it by navigating to any site and clicking "API Playground" in the sidebar.
The playground provides:
- Endpoint browser - Browse all available API endpoints
- Parameter controls - Configure request parameters with a visual interface
- Exact time ranges - Test date ranges with optional start and end times
- Live responses - See real API responses with your actual data
- Code generation - Copy ready-to-use code snippets
This is the recommended way to familiarize yourself with the API before integrating it into your applications.
Guides
Looking for what to build with the API? These end-to-end recipes chain endpoints together to solve a real problem:
- Automated Weekly Report — a scheduled digest of last week's traffic, week-over-week change, and top pages and sources.
- Find Where Users Drop Off — locate the biggest leak in a funnel, then see where the people who abandon go instead.
- Compare Channel Performance — rank acquisition channels by how well they convert, not just how much traffic they send.
- Build a Live Visitor Feed — poll the events endpoint for a real-time activity stream you can render or alert on.
- Export Events to a Warehouse — backfill your full event history and keep it in sync with an incremental job.
Authentication
All API requests must include authentication using one of the following methods:
Bearer Token (Recommended)
Authorization: Bearer your_api_key_hereQuery Parameter (Testing Only)
?api_key=your_api_key_hereQuery parameters expose API keys in server logs and browser history. Use only for quick testing.
Generating API Keys
Rybbit has two kinds of API keys:
- Organization API keys (recommended for integrations) — the organization's own credential. They can access every site in the organization and keep working when team members leave. Only organization admins and owners can create and manage them.
- Personal API keys — act as you, with exactly your access, including any site restrictions, across every organization you belong to. Best for personal scripts and for connecting MCP clients.
Organization keys
- Navigate to Settings → Organization in your Rybbit dashboard
- Scroll to the Organization API Keys section (visible to admins and owners)
- Enter a name for the key and click Create
- Copy the key immediately (it won't be shown again)
Personal keys
- Navigate to Settings → Account in your Rybbit dashboard
- Scroll to the Personal API Keys section
- Enter a name for the key and click Create
- Copy the key immediately (it won't be shown again)
Both kinds support restricting a key to specific permissions when you create it — leave restrictions off for a full-access key.
Rate Limits (Cloud Only)
Requests are limited in two ways: a burst limit that is the same on every plan, and a daily quota that depends on your plan.
| Plan | Burst | Daily quota |
|---|---|---|
| Free / Basic | API keys not available | — |
| Standard | 50 requests per 10 seconds | 5,000 requests per day |
| Pro | 50 requests per 10 seconds | 25,000 requests per day |
The burst limit is a bucket of 50 requests that refills continuously at 5 requests per second. You can spend all 50 at once, then keep going at 5 per second — so short spikes are fine and there is no window boundary to line up with.
The daily quota resets at 00:00 UTC.
Requests refused by the burst limit don't count against your daily quota.
Which budget a request is charged to
Limits apply per credential owner, never per key — creating more keys splits an existing budget rather than adding to it:
| Credential | Budget |
|---|---|
Organization key (rb_org_) | The organization's. All of an organization's keys share it. |
| Personal key | Yours. All of your personal keys share one budget, across every organization you belong to. |
| OAuth token (MCP) | Yours, the same budget as your personal keys. |
A personal key's quota follows the most generous plan among the organizations you belong to.
Self-hosted instances are not rate limited at all — neither tier applies, and no rate limit headers are sent.
Reading your remaining budget
Analytics and management endpoints report your current budget on every response, so you can pace a client without waiting to be rejected:
| Header | Meaning |
|---|---|
X-RateLimit-Burst-Limit / -Remaining | Burst bucket size and tokens left |
X-RateLimit-Burst-Reset | Seconds until the bucket is full again |
X-RateLimit-Daily-Limit / -Remaining | Daily quota and requests left today |
X-RateLimit-Daily-Reset | Seconds until 00:00 UTC |
RateLimit-Limit / -Remaining / -Reset | Whichever of the two is closest to running out |
Treat these as advisory: a few endpoints resolve credentials outside the standard path and omit them. Retry-After on a 429 is always present.
When you hit a limit
A 429 names the limit you hit and tells you how long to wait, in seconds:
{
"error": "Rate limit exceeded",
"scope": "daily",
"limit": 5000,
"retryAfter": 34200
}scope is burst or daily, and the same value is in the Retry-After header. The difference matters: a burst rejection clears in about a second, while a daily one lasts until the quota resets. Back off accordingly rather than retrying straight away.
Common Parameters
The following parameters are shared across all analytics endpoints.
Time Parameters
All endpoints require date-based, exact datetime, or relative time parameters:
Prop
Type
Note: You must provide either:
- All three date parameters (
start_date,end_date,time_zone), OR - All three exact datetime parameters (
start_datetime,end_datetime,time_zone), OR - Both relative parameters (
past_minutes_start,past_minutes_end)
Examples
Date-based query (last 30 days):
?start_date=2024-01-01&end_date=2024-01-31&time_zone=America/New_YorkExact datetime query (8 AM to 10 AM in New York on Jan 15, sent as UTC):
?start_datetime=2024-01-15%2013:00:00&end_datetime=2024-01-15%2015:00:00&time_zone=America/New_YorkRelative query (last 60 minutes):
?past_minutes_start=60&past_minutes_end=0Filter Parameters
The filters parameter accepts a JSON-encoded array of filter objects to narrow down your data.
Filter Object Structure
Prop
Type
Filter Types
Prop
Type
Available Filter Parameters
Browser & Device
Prop
Type
Location
Prop
Type
Page & Traffic
Prop
Type
UTM Parameters
Prop
Type
User & Events
Prop
Type
Filter Examples
[
{
"parameter": "country",
"type": "equals",
"value": ["US"]
}
]Multiple filters use AND logic:
[
{
"parameter": "country",
"type": "equals",
"value": ["US", "CA"]
},
{
"parameter": "device_type",
"type": "equals",
"value": ["mobile"]
}
]Substring match:
[
{
"parameter": "pathname",
"type": "contains",
"value": ["/blog"]
}
]Pattern match:
[
{
"parameter": "pathname",
"type": "regex",
"value": ["^/products/[0-9]+$"]
}
]Geolocation comparison:
[
{
"parameter": "lat",
"type": "greater_than",
"value": ["37.0"]
},
{
"parameter": "lat",
"type": "less_than",
"value": ["38.0"]
}
]?filters=%5B%7B%22parameter%22%3A%22country%22%2C%22type%22%3A%22equals%22%2C%22value%22%3A%5B%22US%22%5D%7D%5DError Responses
All endpoints return standard HTTP status codes:
- 200 - Success
- 400 - Bad Request (invalid parameters)
- 401 - Unauthorized (missing or invalid API key)
- 403 - Forbidden (no access to site)
- 404 - Not Found (site doesn't exist)
- 429 - Too Many Requests (rate limit exceeded)
- 500 - Internal Server Error
Error Response Format
{
"error": "Error message describing what went wrong"
}