Documentation

Overview

Comprehensive API documentation for Nox.

The Nox API is a RESTful HTTP API that lets you interact with the Nox platform programmatically. All routes are prefixed with /api and return JSON. The documentation below is generated from the OpenAPI specification.

Base URL

Replace {server} with the hostname of the Nox instance you are targeting (e.g. nox.example.com).

https://{server}/api

The actual API root URL is advertised by the server through a well-known discovery mechanism. Clients should resolve it automatically rather than hardcoding the scheme or port.

Server discovery

Given a bare hostname (e.g. nox.example.com), clients attempt the following strategies in order, stopping at the first success:

DNS SRV record

Look up _nox._tcp.<server>. Each SRV record provides a target hostname and port. The client tries https then http for each record, sorted by priority then weight.

_nox._tcp.example.com.  IN  SRV  10 100 443 nox.example.com.

DNS TXT record

Cloudflare compatibility

The TXT record method is a fallback for Proxy Cloudflare issues.

Look up _nox.<server>. Any record containing ng=<url> is followed directly.

_nox.example.com.  IN  TXT  "ng=https://nox.example.com/.well-known/nox"

Fetch /.well-known/nodeinfo and follow the link whose rel is nox/1.0.

/.well-known/nodeinfo
{
  "links": [
    { "rel": "nox/1.0", "href": "https://nox.example.com/.well-known/nox" }
  ]
}

Manual fallback

Fetch /.well-known/nox directly (tries https then http). The response is a NoxWellKnown document describing the server's API root and capabilities.

Caching

The TTL of the resolved URL is derived from the HTTP response headers (Cache-Control: max-age or Expires). Fall back to 5 minutes when no caching header is present.

Authentication

Most endpoints require a Bearer token obtained from POST /api/auth/login or POST /api/auth/register.

Pass the token in the Authorization header of every authenticated request:

Authorization: Bearer <token>

Token lifetime

Tokens are tied to a session. Call POST /api/auth/logout to invalidate the current token.

Response envelope

Every response (except Fediverse and Storage endpoints) is wrapped in a consistent envelope:

Success
{
  "data": { "id": "1@nox.example.com", "username": "alice" },
  "error": null,
  "time": 1700000000000,
  "request": "/api/users/me"
}
Error
{
  "data": null,
  "error": {
    "code": "USER_NOT_FOUND",
    "message": "No user found with this identifier.",
    "status": 404
  },
  "time": 1700000000000,
  "request": "/api/users/1@nox.example.com"
}
FieldTypeDescription
dataobject | nullThe response payload on success, null on error.
errorobject | nullError details on failure, null on success.
error.codestringMachine-readable error code (e.g. USER_NOT_FOUND).
error.messagestringHuman-readable description of the error.
error.statusnumberHTTP status code repeated inside the body.
timenumberUnix timestamp (ms) at which the response was produced.
requeststringThe request path that was processed.

Nox Identifiers

Resources are identified by a NoxIdentifier — a compact, URL-safe string that encodes a resource type, a numeric or named ID, optional query parameters, and an optional server address.

Full format

[<type>:]<id>[?<key>=<value>[&<key>=<value>...]][@<server>]

All parts except <id> are optional. When @<server> is omitted the identifier refers to a resource on the local server.

Type prefixes

PrefixResourceID format
(none)Generic / untypednumeric or string
u:Usernumeric ID or username string
w:Worldnumeric ID
i:Instancenumeric ID or shortname

Query parameters embedded in identifiers

Query parameters are appended after a ? and before the optional @<server> part. They allow passing context or options together with the identifier, without adding extra URL parameters.

World (w:) queries

KeyTypeDescription
vushortAsset version to load (e.g. v=3 selects version 3 of the world's asset bundle).

Instance (i:) queries

KeyTypeDescription
wstring (base64)NoxIdentifier of the world to join, encoded in base64.
pstring (base64)Password required to join the instance, encoded in base64.

Examples

1@nox.example.com                       # untyped resource #1 on remote server
u:1@nox.example.com                     # user #1 on remote server
u:alice                                 # user "alice" on the local server
w:42@nox.example.com                    # world #42 on remote server
w:42?v=3@nox.example.com               # world #42, asset version 3
i:lobby                                 # instance with shortname "lobby" on local server
i:7?w=NDJAbm94LmV4YW1wbGUuY29t         # instance #7 joining world encoded in base64
i:7?w=NDJAbm94LmV4YW1wbGUuY29t&p=c2VjcmV0  # same, with password

Base64 encoding

The w and p query values inside instance identifiers are standard base64 strings (no padding required). Encode the plain NoxIdentifier of the target world before embedding it.

Pagination

List endpoints return a paginated envelope inside data:

{
  "data": {
    "total": 120,
    "limit": 20,
    "offset": 0,
    "items": [ "..." ]
  }
}

Control pagination with the limit and offset query parameters.

Asset upload flow

Uploading binary assets (avatars, worlds) is a three-step process:

Create asset slot

PUT /api/assets

Returns a new asset object including an id field.

Upload file

POST /api/assets/{id}/file
Content-Type: multipart/form-data

Returns 202 Accepted with an ApiAssetJobStatusDto ({ jobId, status }).

Poll for completion

GET /api/assets/{id}/status

Poll until status === "completed". Once complete the asset is available for use.

API groups

Fediverse

The Fediverse endpoints (/.well-known/*, /nodeinfo/*) follow their respective protocol standards and do not use the response envelope described above. They return plain JSON or XML as required by the protocol.

Error codes

Common HTTP status codes returned by the API:

StatusMeaning
200Success
201Resource created
202Accepted (async job started)
400Bad request — invalid parameters
401Unauthorized — missing or invalid token
403Forbidden — insufficient permissions
404Resource not found
409Conflict — e.g. duplicate username
500Internal server error

On this page