RIIP Server Intelligence API
A tiered REST API for live Roblox server, discovery, trend, and forecast data. Scoped bearer keys, per-call metering, cursor pagination, and signed webhooks. Base URL https://api.riip.gg/v1.
Introduction
The RIIP Server Intelligence API exposes the same live data that powers our Smart Server Finder: ranked live servers, quality-first discovery, momentum trends, and AI occupancy forecasts. Every response is JSON, every call is metered, and every response carries a credits_used field plus rate-limit headers so you always know where you stand.
All requests go to https://api.riip.gg/v1 over HTTPS. The API is versioned in the path — the current version is v1. Breaking changes ship under a new path prefix (e.g. /v2); additive fields are rolled into the current version and are always safe to ignore. We recommend tolerant JSON parsing that ignores unknown fields.
Authentication
Authenticate every request with a bearer API key in the Authorization header: Authorization: Bearer rk_live_.... Keys are scoped — each key carries only the permissions you grant it, and a call to an endpoint outside a key's scope returns 403 forbidden.
Mint keys from the dashboard. The full secret is shown once at creation and stored only as a hash on our side — copy it immediately. To rotate, mint a replacement, deploy it, then revoke the old key; both work during the overlap so you get zero-downtime rotation. Never embed a key in client-side code or commit it to source control; treat rk_live_ keys as production secrets.
Scopes
| Scope | Grants |
|---|---|
| servers:read | Live server discovery, occupancy and health. |
| discovery:read | Quality-ranked game search and recommendations. |
| trends:read | Trending and top-games rankings. |
| forecasts:read | Predicted regional occupancy and demand. |
| account:read | Read metered usage for the key's account. |
| webhooks:read | List registered webhook endpoints. |
| webhooks:write | Register and delete webhook endpoints. |
Rate limits
Rate limits are enforced per key on a fixed one-minute window and scale with your plan. Every response — success or error — includes the headers below so you can pace requests without guessing.
| Plan | Rate limit | Monthly quota | Overage | Includes |
|---|---|---|---|---|
| Free | 60 req/min | 1,000 calls/mo | Hard cap — no overage | Server data (servers:read, account:read) |
| Dev | 120 req/min | 100,000 calls/mo | $2.00 / 1,000 calls | + Discovery & webhooks (discovery:read, webhooks:*) |
| Pro | 600 req/min | 1,000,000 calls/mo | $1.00 / 1,000 calls | + Trends, forecasts & analytics (trends:read, forecasts:read) |
Response headers
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests permitted in the current fixed window (per plan). |
| X-RateLimit-Remaining | Requests still available in the current window. |
| X-RateLimit-Reset | Unix epoch seconds at which the window resets and Remaining refills. |
| Retry-After | Seconds to wait before retrying. Present on every 429 and 503 response. |
When you exceed the window you get 429 rate_limited with a Retry-After header. Back off using the header value, or exponentially (1s, 2s, 4s, 8s…) with jitter if it is absent, and never retry faster than X-RateLimit-Reset. A sustained overage on the monthly quota also returns 429 rather than silently billing you — you stay in control.
Metering & billing
Every successful response includes credits_used — the credit cost of that single call. Most reads cost 1 credit; heavier AI endpoints (recommendations, trends, forecasts) cost more, and metering reads like GET /v1/account/usage are free. Credits aggregate into your monthly quota; poll /v1/account/usage for live period totals.
Once you exceed the calls included in your plan, additional calls bill at your plan's overage rate ($2.00/1k on Dev, $1.00/1k on Pro) and appear on the next monthly invoice. The Free plan has no overage — it hard-caps at the quota. For non-idempotent calls (webhook registration), pass an Idempotency-Key header; we de-duplicate retries carrying the same key for 24 hours so a network retry never double-charges or double-creates.
Errors
Errors use standard HTTP status codes and a single JSON envelope. The error.code is a stable machine-readable string; error.message is a human-readable explanation that may change. Branch on code, never on the message text.
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | The request was malformed — bad JSON body, unknown parameter, or wrong value type. |
| 401 | unauthorized | The Authorization header is missing, malformed, or the key was revoked. |
| 403 | forbidden | The key is valid but lacks the required scope, or the resource belongs to another account. |
| 404 | not_found | No resource matches the path — an unknown server_id, game slug, or webhook id. |
| 422 | unprocessable_entity | Syntactically valid but semantically rejected — e.g. horizon_days above the allowed maximum. |
| 429 | rate_limited | The per-minute rate limit or the monthly quota was exceeded. Honor Retry-After. |
| 500 | internal_error | An unexpected error on our side. Safe to retry idempotent (GET) calls with backoff. |
| 503 | service_unavailable | A dependency is degraded or the API is in maintenance. Retry after the Retry-After delay. |
Pagination
List endpoints are cursor-paginated. Pass limit to size a page and read next_cursor from the response; feed it back as the cursor parameter to fetch the following page. Cursors are opaque, stable, and safe to hold across requests. When next_cursor is null you have reached the last page.
Endpoints
Ten endpoints across servers, discovery, trends, forecasts, account usage, and webhook management. Each lists its required scope, minimum plan, and credit cost, with a runnable request and a realistic response.
Best live servers for a game.
Returns a ranked list of live, joinable servers for a game, scored by our quality model (low ping, healthy fill, low crash rate, no exploiter flags). Pair with the `region` and `fill` filters to route a player to the server they actually want — a fresh low-fill lobby or a near-full high-energy one.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| game | query | string | required | Game slug or numeric place id, e.g. blade-ball or 189707. |
| region | query | string | optional | Preferred region: us-east, us-west, eu, asia, oce, sa. Defaults to the caller's inferred region. |
| fill | query | enum | optional | Target fill level: low, medium, or high. Biases ranking toward emptier or fuller servers. |
| limit | query | integer | optional | Max results to return, 1–50. Defaults to 10. |
Example request
Example response
Results are ordered best-first. quality is a 0–100 composite; join_url is a deep link the player can open directly.
Occupancy & health for one server.
Returns live occupancy, latency, and a health verdict for a single server previously returned by servers/find. Use it to re-check a server just before you route a player, since fill and health move in seconds.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| server_id | query | string | required | Server id from a prior servers/find result, e.g. eu-w-9f3a2. |
Example request
Example response
health is one of healthy, degraded, or full. A 404 with code not_found means the server has since closed.
Quality-ranked game search.
Full-text game search ranked by our anti-clone quality model rather than raw play counts, so original, well-retained experiences surface above low-effort copies. Cursor-paginated for building browse and autocomplete surfaces.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| q | query | string | required | Search query, e.g. "anime fighting" or a partial title. |
| genre | query | string | optional | Restrict to a genre, e.g. rpg, simulator, fighting, tycoon, horror. |
| limit | query | integer | optional | Results per page, 1–50. Defaults to 20. |
| cursor | query | string | optional | Opaque cursor from a prior response's next_cursor. Omit for the first page. |
Example request
Example response
originality is a 0–1 anti-clone score. When next_cursor is null there are no further pages.
"Games like X" recommendations.
Returns games similar to a seed title using our embedding vectors over gameplay, audience, and retention signals — not just shared tags. Ideal for "more like this" rails and cross-promotion.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| game | query | string | required | Seed game slug or place id to find neighbours for. |
| limit | query | integer | optional | Number of recommendations, 1–25. Defaults to 10. |
Example request
Example response
similarity is cosine distance in [0,1]; results are ordered most-similar-first.
Trending & top games by genre.
Ranks games by momentum over a rolling window, blending concurrent players with growth rate so fast-climbing titles surface before they peak. Filter by genre to track a single category.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| genre | query | string | optional | Restrict to a genre, e.g. simulator. Omit for the overall board. |
| window | query | enum | optional | Trend window: 24h, 7d, or 30d. Defaults to 24h. |
| limit | query | integer | optional | Number of games to return, 1–100. Defaults to 25. |
Example request
Example response
growth_pct is the percentage change in CCU across the window; negative values indicate cooling titles.
Predicted demand by region.
Forecasts expected concurrent players and server demand per region over a horizon, so you can pre-warm capacity, schedule events, or time sponsored placements to a game's regional peaks. Backed by our AI-native occupancy model.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| game | query | string | required | Game slug or place id to forecast. |
| region | query | string | optional | Restrict the forecast to one region, e.g. us-east. Omit for all regions. |
| horizon_days | query | integer | optional | Days to forecast forward, 1–14. Defaults to 7. Values above 14 return 422. |
Example request
Example response
confidence is the model's 0–1 self-reported certainty; peak_hour_utc is the predicted daily peak in UTC.
Current-period metered usage.
Returns the calling key's account usage for the current billing period — calls made, quota, credits consumed, and projected overage. Metering reads are free and do not count against your quota.
Parameters
No parameters. The key in the Authorization header identifies the account.
Example request
Example response
credits_used aggregates the per-call credit cost; overage begins once calls_made exceeds calls_included.
Register a webhook endpoint.
Registers an HTTPS endpoint to receive signed event deliveries. The response includes a per-endpoint signing secret (shown once) you use to verify the X-RIIP-Signature header on each delivery.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| url | body | string | required | HTTPS endpoint to deliver events to. Must be publicly resolvable; private and loopback ranges are rejected. |
| events | body | string[] | required | Event types to subscribe to, e.g. ["usage.threshold_reached", "billing.payment_failed"]. |
Example request
Example response
Store signing_secret now — it is never returned again. A url in a private/loopback range returns 422 unprocessable_entity.
List registered webhooks.
Returns every webhook endpoint registered on the account, with its subscribed events and recent delivery status. Signing secrets are never included.
Parameters
No parameters. The key in the Authorization header identifies the account.
Example request
Example response
status is active or disabled; endpoints are auto-disabled after repeated delivery failures (see Webhooks).
Delete a webhook.
Permanently removes a webhook endpoint. In-flight deliveries already queued may still arrive; no new events will be sent. Responds 204 No Content on success.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string | required | Webhook id to delete, e.g. wh_3kd91a. |
Example request
Example response
A successful delete returns an empty body. Deleting an unknown id returns 404 not_found.
Webhooks
Register an HTTPS endpoint and RIIP will POST signed JSON events to it as they happen — no polling. Deliveries are signed, retried, and SSRF-guarded. Manage endpoints with the /v1/webhooks endpoints above.
Event types
| Event | Fires when |
|---|---|
| usage.threshold_reached | Metered usage crossed a configured percentage of the monthly quota (e.g. 80%, 100%). |
| billing.invoice_created | A monthly invoice — base plan plus any overage — was finalized for the account. |
| billing.payment_failed | A charge for an invoice was declined. Access enters a grace period until it clears. |
| server.health_changed | A server you subscribed to crossed a health threshold (healthy ↔ degraded ↔ full). |
Example delivery
Verifying the signature
Each delivery carries an X-RIIP-Signature header of the form t=<timestamp>,v1=<hex>. The signature is an HMAC-SHA256 over timestamp + "." + rawBody, keyed by the per-endpoint signing_secret returned when you registered. Compute the same HMAC over the raw request body (not the re-serialized JSON), compare in constant time, and reject deliveries whose timestamp is more than five minutes old to defeat replays.
Retries, DLQ & SSRF
Your endpoint must answer 2xx within 5 seconds. Any non-2xx, timeout, or connection error triggers exponential-backoff retries (roughly 1m, 5m, 30m, 2h, 6h) with jitter over ~24 hours. A delivery that never succeeds lands in a dead-letter queue you can inspect and replay from the dashboard, and an endpoint that keeps failing is auto-disabled and reported via server.health_changed-style status. At registration we validate the target: only public HTTPS hosts are accepted — private, loopback, and link-local ranges are rejected with 422, and each delivery re-resolves DNS to a public address to prevent SSRF via rebinding.
Mint a scoped key, make your first metered call, and wire up a webhook in minutes.