For region owners & developers
Region Monitoring API
A small, read-only HTTPS API that tells you how your region's simulator is doing right now: whether it is running, when the current simulator process started, and its frame rate, frame time, avatars, scripts and prims – measured on the server, not guessed from a viewer.
1. Get a key
- Log in on this website and open Control Panel → Regions, then your region, then Monitoring API keys (or go straight to Monitoring API keys).
- Give the key a name (for example the service that will use it) and choose All my regions or only the regions you pick.
- Press Create key and copy the key. It is shown only once: we store only a fingerprint (SHA-256) of it, so nobody – including us – can show it again. If you lose it, revoke it and make a new one.
Keys look like wtm_ followed by 48 letters and digits. Each owner can have up to 20 active keys. A key can read the regions you own or manage (estate managers listed on the region); that is checked again on every request, so if a region stops being yours the key stops seeing it.
Revoking a key
On the same page, press Revoke next to the key and confirm. It stops working at once, everywhere. Revoking one key does not affect your other keys. The list shows when each key was created and last used (updated at most once a minute).
This key is separate from the region's in-world console key (the Get API Key button), which is for the in-world control HUD.
2. Authentication
Send the key in the Authorization header as a bearer token, over HTTPS:
Authorization: Bearer wtm_your_key_here
- Never put the key in the URL. A request with ?key=, ?api_key= or ?token= is refused with 400 key_in_url – revoke that key, because it may now be in logs.
- HTTPS only. Use https://wolf-grid.com; plain-HTTP requests are redirected, which means your client has already sent the header unencrypted – so always start with https.
- The key is never included in any response.
3. Endpoint & example
GET https://wolf-grid.com/api/v1/regions/{region_id}/status
{region_id} is the region's UUID. It never changes, even if the region is renamed. The Monitoring API keys page lists every region you own or manage with its id; it is also the id=… at the end of the region's page address in the Control Panel.
curl
curl -s https://wolf-grid.com/api/v1/regions/d87eb383-be72-11ec-8d47-005056455866/status \ -H "Authorization: Bearer $WOLF_API_KEY"
Example answer (region online)
{
"api_version": "1.0",
"region_id": "d87eb383-be72-11ec-8d47-005056455866",
"region_name": "Sandbox",
"status": "online",
"server_time_utc": "2026-10-23T18:00:02Z",
"sample_time_utc": "2026-10-23T17:59:55Z",
"sample_age_seconds": 7,
"simulator": {
"instance_id": "6a0f3b1c9e2d4f5a8b7c6d5e4f3a2b1c",
"started_at_utc": "2026-10-23T09:14:31Z",
"uptime_seconds": 31531,
"fps": 55.0,
"frame_time_ms": 18.19,
"agent_count": 2,
"physics_frame_time_ms": 0.42,
"script_frame_time_ms": null,
"active_scripts": 311,
"script_events_per_second": 96.0,
"prims": 8412,
"prim_allowance": 45000,
"pending_downloads": 0,
"pending_uploads": 0,
"time_dilation": 1.0,
"physics_fps": 55.0,
"npc_count": 0,
"fps_actual": 11.0,
"frame_time_ms_actual": 90.95,
"stats_sample_time_utc": "2026-10-23T17:59:51Z",
"stats_age_seconds": 11,
"stats_available": true,
"stats_unavailable_reason": null,
"opensim_version": "OpenSimWolf 0.9.3.9333",
"physics_engine": "BulletSim",
"region_size_m": { "x": 1024, "y": 1024 }
}
}
Values are illustrative.
4. Fields & units
A value that is not known is null, never 0. A 0 is a real measurement. All times are UTC in ISO 8601 (2026-10-23T18:00:02Z), to the second.
| Field | Type | Unit | Meaning |
|---|---|---|---|
| api_version | string | Version of this response format ("1.0"). | |
| region_id | string | UUID | The region's permanent id (stays the same when the name changes). |
| region_name | string | The region's current name. | |
| status | string | online, starting, restarting, stopping or offline - see Status values. | |
| server_time_utc | string | ISO 8601 UTC | When this answer was made. |
| sample_time_utc | string | ISO 8601 UTC | When the region server last read its simulator processes (status, instance, start time). |
| sample_age_seconds | integer | seconds | server_time_utc minus sample_time_utc. Normally under 15 + 5. |
simulator
| Field | Type | Unit | Meaning |
|---|---|---|---|
| instance_id | string|null | 32 hex | Identifies the running simulator process. It changes every time the process starts - after a restart, a crash or a server reboot - and never otherwise. null when no simulator is running. |
| started_at_utc | string|null | ISO 8601 UTC | When the running simulator process started, read from the operating system's record of that process (see below). |
| uptime_seconds | integer|null | seconds | Time since started_at_utc. |
| fps | number|null | frames/s (viewer scale) | Simulator frame rate as the viewer's Statistics bar shows it: 55 is full speed. |
| frame_time_ms | number|null | ms (viewer scale) | Average total frame time on the same scale (18.2 ms = 55 fps). |
| agent_count | integer|null | avatars | Avatars in the region now (root agents, not counting NPCs). A count only - never who. |
| physics_frame_time_ms | number|null | ms (viewer scale) | Time per frame spent in physics. |
| script_frame_time_ms | null | Always null for now: the region's script engine does not measure script time per frame, so we do not report a made-up 0. Use script_events_per_second. | |
| active_scripts | integer|null | scripts | Running scripts in the region. |
| script_events_per_second | number|null | events/s | Script events (timers, touches, listens, sensors...) delivered per second. |
| prims | integer|null | prims | Objects/prims in the region now. |
| prim_allowance | integer|null | prims | The region's configured prim capacity. |
| pending_downloads | integer|null | requests | Asset downloads waiting (queue). |
| pending_uploads | integer|null | requests | Asset uploads waiting (queue). |
| time_dilation | number|null | 0-1 | 1.0 = simulation runs at real time. |
| physics_fps | number|null | frames/s (viewer scale) | Physics frame rate. |
| npc_count | integer|null | NPCs | Scripted NPC avatars (not counted in agent_count). |
| fps_actual | number|null | frames/s | The real number of frames per second (the viewer scale divided by the simulator's normalisation factor, 5 on this grid). |
| frame_time_ms_actual | number|null | ms | The real average frame time (about 91 ms at full speed on this grid). |
| stats_sample_time_utc | string|null | ISO 8601 UTC | When the simulator measured the performance values above (it writes them every 10 s). |
| stats_age_seconds | integer|null | seconds | How old those values are. Over 60 s and they are reported as null. |
| stats_available | boolean | true when the performance values are present and fresh. | |
| stats_unavailable_reason | string|null | Why they are not: simulator_not_running, simulator_update_pending (see below), no_sample_yet, sample_stale, region_stopping. | |
| opensim_version | string|null | Simulator software version. | |
| physics_engine | string|null | Physics engine in use (for example BulletSim or ubODE). | |
| region_size_m | object|null | metres | {"x": width, "y": height}. |
simulator_update_pending: the performance values (fps, frame times, agents, scripts, prims) come from a part of the simulator added on 23 October 2026. A region gets it the next time it restarts. Until then status, instance_id and started_at_utc work normally, and the performance values are null with this reason.
5. Status values
- online
- – the simulator is running and the region has finished starting (logins enabled).
- starting
- – the simulator process is running (or about to be launched) but the region has not finished starting.
- restarting
- – a restart is in progress: the region is shutting down or between processes and will come back by itself.
- stopping
- – the simulator is shutting down and no restart was asked for through the grid's controls.
- offline
- – no simulator is running for the region. You still get a full answer, with the simulator values null.
Watch instance_id to detect restarts and crashes: if it differs from your last poll, a new simulator process started at started_at_utc, even if you never saw the region offline.
6. Errors
Errors are JSON with a fixed shape, and never contain internal details:
{ "error": { "code": "invalid_api_key", "message": "Missing, unknown or revoked API key. ..." } }
| HTTP | code | When |
|---|---|---|
| 400 | invalid_region_id | The id is not a UUID. |
| 400 | key_in_url | A key was put in the query string. Revoke it. |
| 400 | https_required | Not called on https://wolf-grid.com. |
| 401 | invalid_api_key | No key, an unknown key, or a revoked key. |
| 403 | insufficient_scope | The key may not read region status. |
| 404 | region_not_found | No such region, or not one this key may read (both look the same, on purpose). |
| 404 | not_found | Wrong path. |
| 405 | method_not_allowed | Anything but GET (the API is read-only). |
| 429 | rate_limited | Too many requests; wait the number of seconds in Retry-After. |
| 500 | internal_error | A fault on our side. Retry later. |
| 503 | monitoring_unavailable | We could not ask the region's server just now. This is not "offline": it says nothing about the region. The body still has region_id, region_name and "status": "unknown"; Retry-After says when to try again. |
So: 200 with "status": "offline" means the simulator is not running; 503 means our monitoring could not tell.
7. Rate limits & caching
- 60 requests per minute per key. Every answer carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix time the window resets).
- 120 requests per minute per client address, and 10 failed authentications per minute per address.
- Over a limit you get 429 rate_limited with Retry-After in seconds.
- The region server is read at most every 15 seconds and the simulator writes its performance values every 10 seconds, so polling more often than every 15–30 seconds gives you the same data. Use sample_age_seconds and stats_age_seconds to see how fresh each part is.
8. Where the numbers come from
- Start time and instance id come from the Linux kernel's own record of the running simulator process on the region server: the process's start time (/proc/<pid>/stat field 22, in clock ticks since boot, plus the boot time). The instance id is a hash of the server, its boot id, the process id and that start time, so it changes on every process start - including after a crash - and is the same on every poll while that process runs. Neither comes from a database, a viewer, this website or a previous API call. We chose this over the simulator's own clock because it works for every region today and cannot be reset by anything inside the simulator.
- Status comes from the same live process list, plus the region's own "ready" signal (the same moment the simulator enables logins).
- Performance values are the simulator's own statistics (the ones a viewer's Statistics bar shows), written by the simulator every 10 seconds on the region server.
- The website reads them from each region server over a private connection. The simulator's own admin, console and REST interfaces are not used and not exposed.
- Not provided in v1: last shutdown reason and backup status, because we cannot yet report them reliably.
Questions or ideas for v2: contact us.