Relay docs
Relay speaks ER:LC's API. If your bot works with ER:LC today, it works with Relay after you change the base URL and the key.
Getting started
- Sign in at relay.cordyx.xyz/app and add your server with its ER:LC server key.
- Make a key for each bot or developer and tick what it may do. Copy it straight away: Relay stores only a hash and can't show it again.
- Replace
https://api.erlc.ggwithhttps://relay.cordyx.xyz/apiand use the Relay key.
To run commands, ER:LC also needs you to authorize Relay on your server once. The dashboard shows the link after you add a server.
Sending the key
Either header works. Use whichever needs fewer changes in your code.
Server-Key: cxr_…
Authorization: Bearer cxr_…
Relay keys start with cxr_ and are 44 characters long. Don't use them in browser code: anyone who opens the page can read them. Relay sends no CORS headers for that reason.
Endpoints
| Method | Path | Permission |
|---|---|---|
| GET | /api/v1/server | server.read |
| GET | /api/v1/server/players | players.read |
| GET | /api/v1/server/staff | staff.read |
| GET | /api/v1/server/queue | queue.read |
| GET | /api/v1/server/vehicles | vehicles.read |
| GET | /api/v1/server/bans | bans.read |
| GET | /api/v1/server/joinlogs | logs.join |
| GET | /api/v1/server/killlogs | logs.kill |
| GET | /api/v1/server/commandlogs | logs.command |
| GET | /api/v1/server/modcalls | logs.modcalls |
| POST | /api/v1/server/command | the command's group |
| GET | /api/v2/server | server.read, plus one per field |
| POST | /api/v2/server/command | the command's group |
Anything else answers 404 with code 9007.
v2 fields
On GET /api/v2/server, each field you set to true needs its own permission. A field Relay doesn't know is refused, not ignored.
| Field | Permission |
|---|---|
| Players | players.read |
| Staff | staff.read |
| Queue | queue.read |
| Vehicles | vehicles.read |
| JoinLogs | logs.join |
| KillLogs | logs.kill |
| CommandLogs | logs.command |
| ModCalls | logs.modcalls |
| EmergencyCalls | calls.emergency |
Commands
Relay reads the first word of the command and checks it against these groups. A command outside every group is refused for all keys.
| Permission | Group | Commands |
|---|---|---|
| cmd.message | Messages | :h :m :pm :log |
| cmd.moderation | Moderation | :kick :ban :unban :kill :jail :unjail :wanted :unwanted |
| cmd.players | Player actions | :heal :refresh :respawn :load |
| cmd.teleport | Teleport | :tp :bring :to |
| cmd.server | Server settings | :prty :pt :weather :time :startfire :stopfire |
| cmd.staff | Staff permissions | :mod :unmod :admin :unadmin :helper :unhelper |
Limits
- Commands: one every 5 seconds per server, shared by all of that server's keys. That's ER:LC's own limit; Relay answers
429withretry_afterinstead of passing the request on. - Reads: identical requests within 5 seconds get the same answer. The
X-Relay-Cacheheader sayshit,sharedormiss. - 120 requests a minute per key.
- Activity logs are kept for 30 days.
Errors
Errors use ER:LC's shape, {"code": …, "message": "…"}. Codes from ER:LC pass through unchanged. Relay's own are in the 9000s.
| Code | Meaning |
|---|---|
| 9001 | No Relay key was sent. |
| 9002 | That Relay key doesn't exist or was revoked. |
| 9003 | This key isn't allowed to do that. |
| 9004 | That command isn't one Relay knows, so it's refused. |
| 9005 | This key can't be used from this IP address. |
| 9006 | ER:LC refused this server's key. The owner needs to add a new one on the dashboard. |
| 9007 | Relay doesn't proxy that endpoint. |
| 9008 | This key has expired. |
Examples
Python
import os, requests
r = requests.get(
"https://relay.cordyx.xyz/api/v2/server",
params={"Players": "true", "Queue": "true"},
headers={"Server-Key": os.environ["RELAY_KEY"]},
)
print(r.json()["Players"])
curl
curl -X POST https://relay.cordyx.xyz/api/v1/server/command \
-H "Authorization: Bearer $RELAY_KEY" \
-H "Content-Type: application/json" \
-d '{"command": ":h Server restart in 10 minutes"}'