A read-only JSON API for avatar activity. One endpoint, selected with the endpoint query parameter.
https://mon.hails.cc/api.php
All requests are GET. Responses are JSON. Always call https:// directly.
Authentication Endpoints Parameters Errors Tips
One endpoint is public; the rest require a personal bearer token sent in the
Authorization header:
Authorization: Bearer YOUR_TOKEN
Create a token in the dashboard: open the 🔑 API Tokens panel, click Create token, and copy it immediately, it is shown only once. A token can only access the regions your account can access. Revoke a token any time from the same panel.
Tokens are stored hashed; if you lose one, revoke it and create a new one.
| Endpoint | Auth | Purpose |
|---|---|---|
known_bots | public | The complete known-bot list across all regions. Built for estate ban / block lists. |
top_visitors | token | Top visitors of a region, by total time. |
likely_bots | token | Likely bots in a single region. |
region_stats | token | Unique / peak / average for a region + window. |
my_regions | token | What your token can access. |
list_regions | token | Region names you may query (all, if you can view all). |
The complete cross-region bot list, meant to be imported straight into an estate ban or block list. Once an avatar is detected it stays on the list permanently, even if it goes quiet, so a bot that pauses for a month does not silently fall off your ban list. Bots are found two ways: a visit heuristic (many short visits, low average duration), and a name sweep that always includes BonnieBots.
Parameters, all optional: format (json default, text,
csv, ndjson), limit (JSON 1–1000, default 100),
cursor, and sort (visits or key).
A ready-to-import ban list, one UUID per line:
curl 'https://mon.hails.cc/api.php?endpoint=known_bots&format=text' -o banlist.txt
The whole list as a spreadsheet, to review before banning:
curl 'https://mon.hails.cc/api.php?endpoint=known_bots&format=csv' -o known_bots.csv
The default JSON page:
curl 'https://mon.hails.cc/api.php?endpoint=known_bots'
{
"generated_at": "2026-07-13 18:25:08 UTC",
"window": "month",
"total": 1476,
"count": 100,
"sort": "visits",
"next_cursor": "dnwxMDJ8MGM0Ny4uLmMzN2M",
"bots": [
{ "avatar_name": "Some Resident", "avatar_key": "0c47...c37c",
"visit_count": 102, "avg_seconds": 6, "detection_source": "heuristic",
"region_count": 14, "first_detected_at": "2026-05-02 03:11:57",
"last_detected_at": "2026-07-13 18:00:04", "last_seen": "2026-07-13 17:52:10" }
]
}
detection_source is heuristic, bonnie (a BonnieBot), or
manual. The original four fields (avatar_name, avatar_key,
visit_count, avg_seconds) are unchanged, so existing clients keep working.
Walking the whole list in JSON: page with sort=key and follow
next_cursor until it comes back null.
curl 'https://mon.hails.cc/api.php?endpoint=known_bots&sort=key&limit=500'
curl 'https://mon.hails.cc/api.php?endpoint=known_bots&sort=key&limit=500&cursor=NEXT_CURSOR_FROM_THE_LAST_PAGE'
sort=key pages by avatar key, the only ordering that stays stable while the list is
being rebuilt, so a walk can neither skip nor repeat a bot. sort=visits (worst bots
first) is the default for a single unpaged call, but its ordering shifts as visit counts change, so
do not use it to download the whole list. The text, csv and
ndjson formats always return everything and ignore cursor.
The list changes at most once per refresh (roughly every 20 minutes), and every response carries
an ETag and a Last-Modified. Send the ETag back and an unchanged list costs
you nothing but a 304 Not Modified with an empty body, which is the polite way to poll:
curl -i -H 'If-None-Match: "THE_ETAG_FROM_YOUR_LAST_RESPONSE"' \
'https://mon.hails.cc/api.php?endpoint=known_bots&format=text'
Responses also carry X-Total-Count (published bots in the whole registry) and, on a
paged JSON response with more to fetch, X-Next-Cursor.
Required region. Optional window (default month) and
limit (1–50, default 10).
curl -H 'Authorization: Bearer YOUR_TOKEN' \
'https://mon.hails.cc/api.php?endpoint=top_visitors®ion=Lil%20G'
{
"region": "Lil G",
"window": "month",
"visitors": [
{ "avatar_name": "A Resident", "avatar_key": "0c47...c37c",
"visit_count": 102, "total_seconds": 620698, "avg_seconds": 6085 }
]
}
Required region. Optional window, limit (1–100, default 20).
curl -H 'Authorization: Bearer YOUR_TOKEN' \
'https://mon.hails.cc/api.php?endpoint=likely_bots®ion=Lil%20G'
Required region. Optional window (default month).
curl -H 'Authorization: Bearer YOUR_TOKEN' \
'https://mon.hails.cc/api.php?endpoint=region_stats®ion=Lil%20G&window=week'
{ "region": "Lil G", "window": "week", "unique": 214, "peak": 9,
"avg_seconds": 1830, "computed_at": "2026-07-07 18:00:00 UTC" }
No parameters. can_view_all: true returns an empty regions list (the flag
means "everything"); otherwise it lists your assigned regions.
curl -H 'Authorization: Bearer YOUR_TOKEN' \
'https://mon.hails.cc/api.php?endpoint=my_regions'
{ "can_view_all": false, "regions": ["Lil G", "Some Other Sim"] }
No parameters. Returns the exact region names you may query. Every region if your account
can view all, otherwise your assigned regions. Use this to find the exact spelling for the
region parameter above.
curl -H 'Authorization: Bearer YOUR_TOKEN' \
'https://mon.hails.cc/api.php?endpoint=list_regions'
{ "can_view_all": true, "count": 203, "regions": ["A Sim", "Another Sim", "..."] }
| Name | Notes |
|---|---|
region | The exact full region name (not a prefix). Case-insensitive. URL-encode spaces as %20, or use curl -G --data-urlencode. |
window | One of hour, 12h, 24h, week, month (default), year. |
limit | Max rows. Clamped per endpoint (known_bots 1–1000 per JSON page, top_visitors 1–50, likely_bots 1–100). |
format | known_bots only. json (default), text (one UUID per line), csv, or ndjson. Everything except json returns the entire list in one streamed response. |
sort | known_bots only. visits (worst first, the default for a single call) or key (stable ordering, use this to page through the whole list). |
cursor | known_bots only. The next_cursor from your previous page. Opaque: pass it back unmodified. |
Region names with spaces the easy way:
curl -G -H 'Authorization: Bearer YOUR_TOKEN' \
'https://mon.hails.cc/api.php' \
--data-urlencode 'endpoint=top_visitors' \
--data-urlencode 'region=Lil G'
Errors return {"error":"..."} with an HTTP status:
| Status | Meaning |
|---|---|
400 | Missing or invalid parameter (e.g. no region, bad window). |
401 | Missing, malformed, revoked, or expired token; or the account is inactive. |
404 | Unknown endpoint, or a region that does not exist or that your token may not access (both look the same on purpose). |
405 | Method other than GET (known_bots also accepts HEAD). |
list_regions before calling the region endpoints.ETag you got last time and you will get a cheap 304 whenever nothing has changed.format=text for a ban-list importer, and sort=key if you are paging JSON to download the whole list.known_bots once detected, and BonnieBots are always included. A false positive can only be cleared by an administrator, so if you think a real resident is on the list, say so.visit_count, avg_seconds, region_count and last_seen are published so you can apply a stricter bar than ours before banning.