Advertisement
Your 728 by 90 banner could be here. Advertise on revlist.Advertise here →

revlist API

Read the board, vote, claim prizes, and manage a revival from your own backend.

Log in for a key

Overview

The revlist API is a JSON API served from https://revlist.lol/api/v1. Public reads need no authentication. Voting, claiming prizes and managing a revival use an API key created from your API keys page.

Base URL

https://revlist.lol/api/v1

Authentication

Create a key on API keys. It looks like rvl_... and is shown exactly once. Send it as a bearer token:

Authorization: Bearer rvl_your_key_here
# or
X-API-Key: rvl_your_key_here

Scopes: read, vote, claim, and owner. A key may be pinned to a single revival; if it is, owner endpoints for any other revival return 403. Browser sessions are also accepted by every endpoint (with CSRF origin checks on writes).

Response envelope

{
  "data": { ... },
  "meta": { "page": 1, "pages": 3, "total": 44 }
}

Errors always use the same shape. Messages are written for humans: they say what went wrong and, when we can, what to do next. hint is optional but usually tells you the next step, and validation errors also list every bad field.

{
  "error": {
    "code": "validation_error",
    "message": "The headline needs at least 3 characters.",
    "hint": "Fix the fields listed in details.fields, then send the request again. Nothing was saved.",
    "details": {
      "fields": { "headline": "The headline needs at least 3 characters." }
    }
  }
}

Validation errors are 422. Permission problems are 403, missing things are 404, and rate limits are 429.

Rate limits

  • Voting: 20 requests per minute per account and IP.
  • Prize claims: 30 per minute per account.
  • API key creation: 10 per hour per account.
  • Ad orders: 5 per hour per account.

A limited response is 429 with a Retry-After header. Daily voting itself is one vote per revival per UTC day; retrying does not add votes.

Public endpoints

GET/health
Service status. Reports database health. No auth.
GET/revivals
Approved revivals, sorted by votes by default. Query: page, limit (max 50), sort = votes | newest | name, and q to search names and taglines.
GET/revivals/{slug}
One revival with its description, owner, viewer vote status, and active prize pool.
GET/revivals/{slug}/leaderboard
Top voters. Query: limit (default 10, max 100). Ranks are by total votes, ties broken by who reached the count first.
GET/revivals/{slug}/rewards
The prize pool with stock remaining. Public; a signed-in viewer also gets claimed_by_viewer.
GET/ads
Live paid creatives for one placement. Query: placement = sitewide, left, sidebar, or feed. The response is a fresh rotation each request: the side rails can return up to three ads, and a takeover campaign returns alone with fills_slot: true. Click URLs point at revlist so views and clicks stay measurable.
GET/revivals/{slug}/comments
The newest comments on a revival, up to 50. Each author has a link to their member profile.
POST/revivals/{slug}/comments
Post a comment. Body: { "body": "Best 2016 remake around." }. Requires a signed-in member or an API key; comments are 2-1,000 characters and rate limited to 12 every five minutes.
DELETE/revivals/{slug}/comments/{id}
Remove a comment. Allowed for the author, the revival owner and site staff. Deletes are soft, so moderation history is kept.
GET/users/{username}
A public member profile: bio, join date, follower/friend counts, and your relationship to them when you are signed in.

Voting

POST/revivals/{slug}/vote
Requires the vote scope. Records today's vote. Returns counted, the new votes_total, and the next reset time. Browser votes include a Cloudflare Turnstile token in the body; API-key clients do not need one.
curl -X POST https://revlist.lol/api/v1/revivals/classic-2016/vote \
  -H "Authorization: Bearer rvl_your_key"

{
  "data": {
    "counted": true,
    "votes_total": 1731,
    "next_vote_at": "2026-10-23T00:00:00.000Z"
  }
}

Prizes and claims

A revival owner publishes prizes with one of three requirements: vote (any voter), top_voter (current first place), or manual (the team chooses winners; members cannot claim it themselves). A member claim is created with their Roblox username and starts as pending.

POST/me/rewards/{rewardId}/claim
Requires the claim scope. Body: { "robloxUsername": "Builderman", "note": "optional" }. Stock and eligibility are checked under a database lock. Duplicate claims return 409 already_claimed.
GET/me/rewards
Your claims with status, reward, revival and delivery reference.

Owners then mark a claim fulfilled after delivering the currency or item. The delivery_ref is any identifier the revival wants to keep (transaction id, asset id, ticket number).

Owner endpoints

All owner endpoints require the owner scope and ?slug=your-revival. They work for the revival's owner and for site admins.

GET/owner/revival?slug=
Your listing, including status and vote totals.
PATCH/owner/revival?slug=
Update name, tagline, description, invite URL, website, banner or logo. JSON fields:name, tagline, description, inviteUrl, websiteUrl, bannerUrl, logoUrl.
GET/owner/stats?slug=
Votes today, in the last 7 days, unique voters, reward counts, pending claims and recent claims.
GET/owner/rewards?slug=
The full prize pool with stock remaining.
POST/owner/rewards?slug=
Create a prize. Body example:
{
  "title": "Voter stipend",
  "description": "250 Tix for every voter, once.",
  "kind": "tix",
  "amount": 250,
  "requirement": "vote",
  "stock": 5000
}
kind is robux, tix, item or custom. requirement is vote, top_voter or manual. Leave stock out for unlimited.
PATCH/owner/rewards/{id}?slug=
Update any prize field, including active: false to retire it.
DELETE/owner/rewards/{id}?slug=
Retire a prize. Existing claims are preserved.
GET/owner/claims?slug=&status=
Claims for your revival. status = pending, fulfilled, rejected or all (the default). Each row includes the claimant's Discord username and Roblox username.
POST/owner/claims?slug=
Award a manual prize to a chosen member. Body: { "rewardId": 8, "username": "Builderman", "robloxUsername": "Builderman", "note": "Top builder" }. Use discordId instead of username for an exact match. Only manual prizes can be awarded this way; the claim starts as pending and still goes through the fulfil step when the prize is delivered.
POST/owner/claims/{id}/fulfill?slug=
Body: { "deliveryRef": "rbx-txn-12345" }. Marks the claim fulfilled and records who paid it out. Only pending claims can be fulfilled.
POST/owner/claims/{id}/reject?slug=
Body: { "note": "Ineligible" }. Marks a pending claim rejected.

End-to-end prize flow

# 1. A member votes, then claims 250 Tix from the revival page.
# 2. Your backend polls pending claims:
curl "https://revlist.lol/api/v1/owner/claims?slug=classic-2016&status=pending" \
  -H "Authorization: Bearer rvl_owner_key"

# 3. Grant the Tix in-game/on your site, then close the claim:
curl -X POST "https://revlist.lol/api/v1/owner/claims/42/fulfill?slug=classic-2016" \
  -H "Authorization: Bearer rvl_owner_key" \
  -H "Content-Type: application/json" \
  -d '{"deliveryRef":"tix-grant-9001"}'

# 4. The member sees "fulfilled" and the delivery reference on /prizes.

JavaScript example

const API = "https://revlist.lol/api/v1";
const headers = { Authorization: `Bearer ${process.env.REVLIST_KEY}` };

const claims = await fetch(`${API}/owner/claims?slug=classic-2016&status=pending`, {
  headers,
}).then((response) => response.json());

for (const claim of claims.data) {
  await deliverPrize(claim.roblox_username, claim.reward.title);
  await fetch(`${API}/owner/claims/${claim.id}/fulfill?slug=classic-2016`, {
    method: "POST",
    headers: { ...headers, "Content-Type": "application/json" },
    body: JSON.stringify({ deliveryRef: `job-${claim.id}` }),
  });
}

Account endpoints

GET/me
Your profile, Discord token status, vote and claim counts, and the type of credential used.
GET/me/votes
Aggregated vote history by revival.
GET/me/api-keys
List active keys (prefix and scopes only).
POST/me/api-keys
Create a key from a browser session only. Body: { "name": "Backend", "revivalId": 12, "scopes": ["read","owner"] }. The raw key is in the response exactly once.
DELETE/me/api-keys/{id}
Revoke a key immediately.

Ads

Ad placements are sold from the Advertise tab of your dashboard. Orders are paid once, approved by staff, and then rotate in their slot. Impressions and clicks are counted server-side; GET /api/v1/ads is the public read endpoint.

Every slot also has a capacity. The left and right rails show up to three rotating creatives at once; the sitewide banner and in-feed promo hold one and three respectively. Three plans are available:

  • Standard - normal rotation, the slot price.
  • Featured - picked twice as often in the rotation, 175% of the slot price.
  • Takeover - fills the whole slot by itself, 250% of the slot price. Other creatives in that slot wait until the takeover ends.

Plans live in the ad_plans table and can be changed without a code deploy. The public response includes the plan so clients can label a takeover.

GET/owner/ads
Your campaigns with plan, status, dates, and a plain-English performance block: views, clicks, unique_viewers, unique_clickers, click_through_rate_percent, and a daily series. Views and clicks count every event; the unique numbers count distinct people (signed-in accounts plus distinct anonymous IPs).

Verify a revival

Verified owners have proved they control the website listed on the revival. The badge is public on the revival page. Start with POST, publish the DNS record or text file, then PUT to check it.

GET/owner/verification?slug=
Current status, plus the instructions if verification was already started.
POST/owner/verification?slug=
Body: { "method": "dns" } or { "method": "file" }. Returns a TXT record named _revlist.yourdomain.com and a file URL at /revlist-verification.txt. The revival needs a website URL first.
PUT/owner/verification?slug=
Checks the DNS record or file. A mismatch returns 422 with a message explaining what we saw, so you can fix it without guessing.

Members and social

Every member has a profile page at /u/username. Follows are one-way; friendships need both people. Profiles are public, but only signed-in members can follow or add friends.

POST/users/{username}/follow
Follow a member. DELETE unfollows. Returns whether you are following and the new follower count.
POST/users/{username}/friend
Body: { "action": "request" }. Actions: request, accept, decline, cancel, remove. Sending a request to someone who already asked you accepts theirs instead of creating a duplicate.
GET/me/friends
Your friends plus incoming and outgoing requests.
GET/me/messages
Your recent conversations with friends, including the last message and unread count for each one.
GET/me/messages/{username}
The latest 200 messages with a friend. Reading the thread marks their messages as read.
POST/me/messages/{username}
Body: { "body": "See you at the launch." }. Sends up to 2,000 characters to a friend. Messages to strangers are rejected with friends_only.
PATCH/me
Update your profile. Body: { "bio": "I collect 2016 clients." }. Bios are limited to 280 characters.

Terms

Be reasonable: no vote bots, no scraping at abusive rates, and no reselling API access. Prizes are the responsibility of the revival that publishes them. revlist records claims and provides the settlement API; it does not mint Robux or Tix. Breaking these rules can get a key revoked and a listing removed.