API
Servers
The shape of the catalog and how to look a server up by address.
The catalog is one JSON document. Clients read it once and keep it, rather than fetching one file per server.
Top-level fields
| Field | Type | Meaning |
|---|---|---|
apiVersion | string | Always v1 for this document. |
schemaVersion | integer | Version of the server metadata contract these entries came from. |
generatedAt | string | When the catalog was built, in RFC 3339 UTC. Changes on every build. |
version | string | A 16-character hash of the content. It changes only when the content changes. Use it to detect change. |
mediaBaseUrl | string | The base that media paths are resolved against. It is an absolute HTTPS URL. |
servers | array | One entry per published server, sorted by id. |
addresses | object | Lowercase hostname to server id, sorted by hostname. |
wildcardDomains | array | { "domain": ..., "id": ... } entries, sorted by domain. |
Server entries
Each entry contains the fields from metadata, with two changes: primaryColor is uppercase, and media is added.
media contains only the images the server provides. A missing kind means "no custom image for this kind", which is not an error.
Each media entry contains:
| Field | Meaning |
|---|---|
url | Absolute URL of the file. |
sha256 | Hash of the file's bytes, in hexadecimal. |
bytes | Size of the file. |
width, height | Pixel dimensions after publication. |
contentType | image/png or image/webp. |
Example
The example below is the output of the build for the fictional example-server, which is not published. It shows the real structure.
{
"apiVersion": "v1",
"schemaVersion": 1,
"generatedAt": "2026-01-01T00:00:00.000Z",
"version": "3ab29b4e33c896b0",
"mediaBaseUrl": "https://media.owlclient.dev",
"servers": [
{
"id": "example-server",
"name": "Example Server",
"description": "Fictional network used to document and test the Owl server media format. It is not a real server.",
"addresses": [
"play.example.net",
"mc.example.net"
],
"primaryAddress": "play.example.net",
"minecraftVersions": [
"1.8.9",
"1.21.11"
],
"gameTypes": [
"PvP",
"Survival"
],
"primaryColor": "#2E6CF0",
"website": "https://example.net",
"socials": {
"discord": "https://discord.gg/example-server"
},
"media": {
"icon": {
"url": "https://media.owlclient.dev/servers/example-server/icon.9a074acc50d03841.png",
"sha256": "9a074acc50d0384122b6aef8c0e0c1fc1afff62d16306eea38602ab130886fc3",
"bytes": 1656,
"width": 64,
"height": 64,
"contentType": "image/png"
},
"logo": {
"url": "https://media.owlclient.dev/servers/example-server/logo.b28604a9add5f95d.png",
"sha256": "b28604a9add5f95dbdecd0e3f82d7131ac79b5f8d0496f9575ea3cc9e8925faa",
"bytes": 6143,
"width": 512,
"height": 512,
"contentType": "image/png"
},
"background": {
"url": "https://media.owlclient.dev/servers/example-server/background.98406853743f3ca5.webp",
"sha256": "98406853743f3ca50a845e37ec7ab4eeb17a483d3890a25bb89a84c09d729366",
"bytes": 7762,
"width": 1920,
"height": 1080,
"contentType": "image/webp"
},
"banner": {
"url": "https://media.owlclient.dev/servers/example-server/banner.eb0fad94af4418f7.webp",
"sha256": "eb0fad94af4418f7817be7962d5cb760d261641be2d2155c31a4f4868c82c533",
"bytes": 2142,
"width": 1200,
"height": 300,
"contentType": "image/webp"
}
}
}
],
"addresses": {
"mc.example.net": "example-server",
"play.example.net": "example-server"
},
"wildcardDomains": []
}Looking a server up
To find the server for an address the player typed:
- Lowercase the hostname, remove a trailing dot, and remove any
:portsuffix. - Look the result up in
addresses. If it is there, that is the server. - Otherwise, check
wildcardDomains. A hostname matches a domain when it is equal to it, or ends with.followed by the domain. If several match, the longest domain wins. - Otherwise, the catalog has no server for that address.
An exact address always wins over a wildcard.
Known limits of version 1
- Ports are ignored. A hostname identifies one server, even when its network listens on several ports. The catalog cannot describe a different server per port.
- SRV records are not followed. A server reached through an SRV record is matched by the hostname the player typed, not by the SRV target.
- Bedrock is out of scope. Bedrock addresses and ports are not modeled.
- IP addresses are not matched. A server that changes its IP keeps its id and its hostnames.
- Aliases are not inferred. A network with several front-end hostnames lists each one in
addresses.