Feed API

What a game client module sends and receives. Every call but the first carries the token from pairing:

Authorization: Bearer <token>

Base address: http://127.0.0.1:8090/api/v1. The machine-readable description is at openapi.json.

POST/api/v1/pair

Ask for a pairing code Call it once, when the module has no token yet. Show the code and the link in the game.

No token needed.

Request body

FieldTypeDescription
characterrequiredstringThe character the client playsup to 30 characters
serverrequiredstringServer slug or name, for example orionup to 60 characters
platformstringOperating system, for example Windows 11up to 40 characters
modulestringModule name and versionup to 40 characters

Response

FieldTypeDescription
coderequiredstringShow it to the player. It is valid for 15 minutes
urlrequiredstringOpen it to start a guest dashboard, or to add the client to an account
tokenrequiredstringThe client's secret. Store it; it works once the code is used
expiresAtrequiredinteger

POST/api/v1/status

Send the character's state Every 5 to 10 seconds while the client runs. The reply says when to send the next capture.

Request body

FieldTypeDescription
schema"vw.status/1"Payload schema and version
modulerequiredstringName and version of the sending module, for example voidwatch-feed/0.3.0up to 40 characters
onlinerequiredbooleanThe character is logged in
characterrequiredCharacter
character.namerequiredstringCharacter nameup to 30 characters
character.vocationstringVocation, for example Elite Knightup to 30 characters
character.levelrequiredinteger≥ 1, ≤ 5000
character.exprequiredintegerTotal experience points≥ 0
posrequiredPosition
pos.xrequiredintegerMap x≥ 0, ≤ 65535
pos.yrequiredintegerMap y≥ 0, ≤ 65535
pos.zrequiredintegerFloor, 0 to 15; 7 is ground level≥ 0, ≤ 15
capintegerFree capacity, in oz≥ 0
staminaintegerStamina, in minutes≥ 0, ≤ 2520
expPerHourintegerExp per hour as the client measures it≥ 0
routestringThe loaded cavebot routeup to 80 characters
routeOnbooleanThe cavebot is running
labelstringThe route label the bot is atup to 40 characters
routesstring[]Every route the bot can loadup to 100 items
suppliesCounted[]up to 30 items
supplies[].namerequiredstringItem or creature name, as the game writes itup to 60 characters
supplies[].haverequiredintegerHow many the character has now≥ 0
supplies[].wantrequiredintegerHow many the bot keeps in stock, or the task goal≥ 0
tasksCounted[]up to 10 items
tasks[].namerequiredstringItem or creature name, as the game writes itup to 60 characters
tasks[].haverequiredintegerHow many the character has now≥ 0
tasks[].wantrequiredintegerHow many the bot keeps in stock, or the task goal≥ 0
lootLootItem[]up to 200 items
loot[].namerequiredstringItem nameup to 60 characters
loot[].countrequiredintegerLooted since the session started≥ 0
loot[].sellintegerNPC price per item, if the module knows it. The server fills it in otherwise≥ 0
lootHoursnumberHours since the loot counter started≥ 0
skullsSkull[]Skulled players in viewup to 20 items
skulls[].namerequiredstringPlayer nameup to 30 characters
skulls[].skullrequired"white" | "red" | "black" | "yellow" | "green" | "orange"Skull colour
blessedbooleanOnly on servers with blessings
redemptionLeftintegerOnly on servers with redemption≥ 0

Response

FieldTypeDescription
okrequiredboolean
statusEveryrequiredintegerSeconds until the next status: 2 while someone watches the character, 30 otherwise
captureEveryrequiredintegerSeconds until the next capture: short while someone watches or an alert fired
commandsrequiredintegerCommands waiting; fetch them from /api/v1/commands
settingsSettingsThe player's module settings, for example minimap: true

GET/api/v1/wait

Wait for a change A long poll: the answer comes the moment someone opens the character on the dashboard, an alert fires or a command is sent, or after `timeout` seconds (at most 25). Keep one open while the client runs, so it switches to the fast pace within a second and costs no requests while nothing happens.

Response

FieldTypeDescription
wakerequiredbooleanTrue when something changed before the timeout
statusEveryrequiredinteger
captureEveryrequiredinteger
commandsrequiredinteger

POST/api/v1/minimap

Send the minimap file The client's minimap<version>.otmm, as it is on disk, at most 40 MB. It becomes the player's own map for the server. Send it when the file changed and the reply's settings say minimap: true.

Request body

application/octet-stream

Response

any

POST/api/v1/capture

Send a screenshot The game window as JPEG or PNG, at most 2 MB. Send one when /status says so.

Request body

image/jpeg, image/png

Response

any

GET/api/v1/commands

Fetch waiting commands Commands the player sent from the dashboard, oldest first. Fetching marks them as sent.

Response

Command[]

POST/api/v1/commands/{cid}/result

Report how a command went

Request body

FieldTypeDescription
okrequiredboolean
messagestringShown in the command logup to 200 characters

Response

any

Errors

A payload that does not match the schema gets status 422 with every problem listed:

{
  "error": "invalid payload",
  "problems": [
    {
      "field": "pos.z",
      "message": "Input should be less than or equal to 15"
    }
  ],
  "schema": "/developers/schema"
}

Status 401 means the token is unknown or the player revoked the client. Pair again to get a new one.