Public reactions API

Better Likes collects one piece of data that's genuinely interesting on its own: the aggregate reaction counts of pages across the web. The plan is to expose that data as a small, read-only HTTP API anyone can build on.

Principles

Planned endpoints

1 · Per-target reactions

Get the full reaction breakdown for one public target — a Facebook post, a GitHub repo, an Amazon product, and whatever else is supported by the time the endpoint ships.

GET /v1/reactions/{site}/{targetId}

{
  "site": "github",
  "targetId": "khasky/betterlikes",
  "total": 1284,
  "counts": {
    "❤️": 612,
    "🔥": 301,
    "👍": 189,
    "🎉": 102,
    "🤔": 80
  },
  "lastUpdated": 1747560000000
}

2 · Batch reads

The same shape, multiplexed. Useful for embedding counts on a listing page where you have many targets in one render.

GET /v1/reactions/batch?t=github/khasky/betterlikes&t=amazon/B08N5WRWNW

3 · Top pages

The most-reacted-to targets across a site, or globally, optionally windowed to a recent period. Useful for "what's everyone talking about right now" boards.

GET /v1/top?site=github&window=24h&limit=50

{
  "window": "24h",
  "items": [
    { "site": "github", "targetId": "user/repo",    "total": 921 },
    { "site": "github", "targetId": "user/other",   "total": 743 },
    ...
  ]
}

Supported windows under consideration: 1h, 24h, 7d, 30d, all.

4 · Trending

Targets ranked by the rate of reactions in a window rather than the absolute count. A two-day-old post that gained 500 reactions today beats a five-year-old post that has 50 000 lifetime reactions but none today.

GET /v1/trending?site=facebook&window=1h&limit=20

5 · Emoji popularity

Which emojis are most-used as reactions — globally, per site, or per time window. Answers "what does the modern web feel like today?" in one chart.

GET /v1/emojis?site=&window=7d&limit=25

{
  "window": "7d",
  "items": [
    { "reaction": "❤️", "count": 184_402 },
    { "reaction": "🔥", "count":  97_215 },
    { "reaction": "👍", "count":  88_117 },
    ...
  ]
}

6 · Site activity

Time-bucketed totals per site: reactions per hour or per day, suitable for sparkline charts and longitudinal research. No targets, no users — just the count of votes landing in each bucket.

GET /v1/activity?site=amazon&bucket=hour&range=24h

7 · Aggregate site stats

A one-line summary per site: total reactions ever recorded, total targets observed, number of supported items by category, and the timestamp of the most recent reaction.

GET /v1/sites/{site}/stats

{
  "site": "github",
  "totalReactions": 412_900,
  "uniqueTargets":   18_204,
  "topReactions": [ "❤️", "🔥", "👍", "🎉", "💯" ],
  "lastReactionAt":   1747560000000
}

8 · Discovery

A machine-readable manifest of which sites the extension currently supports and the schema version of their target IDs. Useful for third-party clients that want to mirror the supported list.

GET /v1/sites

{
  "sites": [
    { "id": "facebook", "label": "Facebook", "schemaVersion": 1 },
    { "id": "github",   "label": "GitHub",   "schemaVersion": 1 },
    { "id": "amazon",   "label": "Amazon",   "schemaVersion": 1 }
  ]
}

Embeds and widgets

Beyond raw JSON, two convenience surfaces are on the roadmap so non-engineers can embed counts on a blog or a project page:

Rate limits and fair use

Every endpoint will sit behind a per-IP rate limit chosen so a normal dashboard never hits it. Heavy users — research crawlers, public dashboards with global reach — should reach out before the first launch so the budget can be tuned rather than tripped.

Responses will set X-RateLimit-Remaining and X-RateLimit-Reset headers, and a 429 will always include a Retry-After value. Edge caching means most repeat fetches are free at the client.

What it will not do