Getting started
Authentication
Mint a short-lived WebSocket token from your API key, then open the connection. The two-step flow keeps your API key off the wire after handshake.
curl -X POST https://fast.corex.gg/v1/token \
-H "Authorization: Bearer sk-corex-..."const r = await fetch("https://fast.corex.gg/v1/token", {
method: "POST",
headers: { Authorization: "Bearer sk-corex-..." },
});
const { token, expiresAtMs } = await r.json();import httpx
r = httpx.post(
"https://fast.corex.gg/v1/token",
headers={"Authorization": "Bearer sk-corex-..."},
)
data = r.json()
token = data["token"]
expires_at_ms = data["expiresAtMs"]req, _ := http.NewRequest("POST", "https://fast.corex.gg/v1/token", nil)
req.Header.Set("Authorization", "Bearer sk-corex-...")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var body struct {
Token string `json:"token"`
ExpiresAtMs int64 `json:"expiresAtMs"`
}
json.NewDecoder(resp.Body).Decode(&body)#[derive(serde::Deserialize)]
struct TokenResponse {
token: String,
#[serde(rename = "expiresAtMs")]
expires_at_ms: u64,
}
let resp: TokenResponse = reqwest::Client::new()
.post("https://fast.corex.gg/v1/token")
.bearer_auth("sk-corex-...")
.send()
.await?
.json()
.await?;require "net/http"
require "json"
uri = URI("https://fast.corex.gg/v1/token")
req = Net::HTTP::Post.new(uri, "Authorization" => "Bearer sk-corex-...")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
body = JSON.parse(res.body)
token = body["token"]
expires_at_ms = body["expiresAtMs"]CoreX uses a two-step authentication flow:
- API key (
sk-corex-...): long-lived secret kept on your backend - WebSocket token (
ws-...): short-lived credential for the WebSocket upgrade
The two steps keep your API key off the wire after handshake. It never appears in WebSocket query strings or connection logs.
Step 1: mint a token
POST your API key to /v1/token. The response contains a token valid for 10 minutes and the exact expiry timestamp.
POST /v1/token HTTP/1.1
Host: fast.corex.gg
Authorization: Bearer sk-corex-...
Response:
{
"token": "ws-AbCdEfGhIjKlMnOpQrStUvWxYz_-0123456789abcd",
"expiresAtMs": 1780000600000
}
expiresAtMs is a Unix timestamp in milliseconds. Use it to schedule a fresh mint before reconnecting.
Step 2: open the WebSocket
Open a WebSocket connection to /v1?token={token}. The token is checked at upgrade. The socket stays open until you close it or the network drops.
wss://fast.corex.gg/v1?token=ws-...
As soon as the connection is up, your handles are active and events start flowing. There is no subscribe message to send; your handle set is configured.
Token lifetime
- Tokens are valid for 10 minutes after mint
- The token is only checked at WebSocket upgrade. An open connection survives token expiry
- The token rides in the query string because WebSocket handshakes can’t carry custom
Authorizationheaders cross-origin. Your long-lived API key never appears in URLs
Errors
All errors return JSON with a single error field.
| HTTP | Body | When |
|---|---|---|
401 | {"error":"invalid_key"} | Missing or invalid API key |
403 | {"error":"forbidden_ip"} | Source IP not in your allowlist (see IP allowlist) |
405 | {"error":"method_not_allowed"} | Request was not POST |
429 | {"error":"rate_limited"} | Too many mint attempts. Includes Retry-After: 60 header |
Rate limits apply per API key and per source IP. On 429, wait the number of seconds in Retry-After before retrying.
Security best practices
- Keep your API key on your backend only. Never embed in client code
- Use the IP allowlist to lock the key to your production servers
- Contact us to rotate your API key if you suspect compromise