Developers
Error handling
The ServerOps error envelope format and all error codes.
Error handling
All errors from the ServerOps API use a consistent JSON envelope. This makes it straightforward to write a single error handler that covers all endpoints.
Error envelope
{
"error": {
"code": "not_found",
"message": "file not found"
}
}code: a stable machine-readable identifier. Use this in your code for branching logic.message: a human-readable description. Do not rely on the exact wording - it may change. Usecodefor logic.
HTTP status codes
| Status | Meaning |
|---|---|
200 OK | Request succeeded |
201 Created | Resource created (uploads, log ingestion) |
400 Bad Request | Request body or parameters are invalid |
401 Unauthorized | Token missing or invalid |
403 Forbidden | Token does not have the required scope |
404 Not Found | Resource does not exist |
409 Conflict | Duplicate request or state conflict |
413 Content Too Large | File exceeds the size limit for your plan |
415 Unsupported Media Type | File type is not allowed |
429 Too Many Requests | Rate limit or quota exceeded |
500 Internal Server Error | Unexpected server error |
Error codes
| Code | Status | Description |
|---|---|---|
unauthorized | 401 | Token missing or revoked |
forbidden | 403 | Token lacks required scope |
not_found | 404 | Resource does not exist |
invalid_input | 400 | Request body failed validation |
quota_exceeded | 429 | Plan quota exhausted |
rate_limited | 429 | Too many requests in the time window |
file_too_large | 413 | File exceeds plan limit |
unsupported_type | 415 | File MIME type not allowed |
internal_error | 500 | Unexpected server error |
Quota exceeded response
When a quota is exceeded the error body includes a snapshot of all your current metrics so you know exactly what was hit:
{
"error": {
"code": "quota_exceeded",
"message": "storage quota exceeded",
"snapshot": {
"storage_bytes": { "used": 10737418240, "limit": 10737418240 },
"file_count": { "used": 4821, "limit": 10000 },
"bandwidth_bytes": { "used": 53687091200, "limit": 107374182400 }
}
}
}Handling errors in code
FiveM Lua
PerformHttpRequest(url, function(statusCode, responseBody)
if statusCode == 200 or statusCode == 201 then
local response = json.decode(responseBody)
-- success
elseif statusCode == 429 then
-- rate limited or quota exceeded
local err = json.decode(responseBody)
if err and err.error and err.error.code == "quota_exceeded" then
print("Quota exceeded. Upgrade your plan at serverops.gg/dashboard/billing")
else
print("Rate limited. Retrying in 10 seconds...")
end
elseif statusCode == 401 then
print("Invalid token. Check your server.cfg")
else
local err = json.decode(responseBody)
print("ServerOps error: " .. (err and err.error and err.error.code or "unknown"))
end
end, "POST", body, headers)Roblox Luau
local ok, result = pcall(function()
return HttpService:RequestAsync(requestOptions)
end)
if ok and result.Success then
local data = HttpService:JSONDecode(result.Body)
-- success
elseif ok then
local err = pcall(function() return HttpService:JSONDecode(result.Body) end)
warn("[ServerOps] Error " .. result.StatusCode .. ":", result.Body)
else
warn("[ServerOps] HTTP request failed:", result)
endRetrying on 429
For rate limit errors (rate_limited), implement exponential backoff:
- On the first
429, wait 1 second and retry. - On the second
429, wait 2 seconds. - On the third
429, wait 4 seconds. - Stop retrying after 3 attempts and log the failure.
For quota errors (quota_exceeded), do not retry - the request will keep failing until the quota resets or you upgrade your plan. Log the error and alert your team.