Error Codes and Troubleshooting

All API errors return an applicable HTTP status code along with this JSON body:

{
  "success": false,
  "error": "Human-readable error description"
}

TLDR

CodeMeaningYour action
200SuccessUse the data
400Bad RequestFix parameters — check the error text
401UnauthorizedCheck API key header/parameter
403ForbiddenThe key is deactivated — contact support
404Not FoundVerify the endpoint path
429Rate LimitedWait for Retry-After, then retry; upgrade if persistent
500Server ErrorRetry once after a delay
501Not Implemented/stream/events — poll instead
503Service UnavailableWait and retry once

Types of errors

Non-standard response format

An empty or non-JSON body means a transient network or server issue. Treat it as a 500: retry once after a short delay; contact support if it repeats.

400 Bad Request

Meaning: invalid or missing parameters. Check the reference; booleans must be true/false; dates ISO-8601; don't repeat a parameter; some combinations (live=true with ended=true) can't go together.

401 Unauthorized

Meaning: authentication failed or the key is missing. Send it as x-api-key (case-insensitive) or apiKey; check for whitespace; make sure you copied the key you were shown.

403 Forbidden

Meaning: the key exists but is deactivated. Email support with the keyID.

404 Not Found

Meaning: the path doesn't exist. Make sure it starts with /v2/.

429 Too Many Requests

Meaning: you exceeded your per-minute limit. Wait for Retry-After seconds; check /account/usage. A rejected call is counted for the minute but never billed.

500 Internal Server Error

Meaning: something went wrong on our end. Retry once after a few seconds; if it persists contact support. Please don't retry in a tight loop.

501 Not Implemented

Meaning: you called /v2/stream/events. SockOdds does not stream; see the polling guide.

503 Service Unavailable

Meaning: temporarily unavailable. Wait and retry once.

Error handling example

async function fetchSockOdds(url, options = {}, canRetry = true) {
  let response, payload, error;
  try { response = await fetch(url, options); payload = await response.json(); } catch (e) { error = e; }
  if (payload?.success === true) return payload.data;
  const status = response?.status;
  if (status === 429 && canRetry) {
    await new Promise((r) => setTimeout(r, 1000 * Number(response.headers.get("retry-after") || 5)));
    return fetchSockOdds(url, options, false);
  }
  const isClientError = payload?.success === false && status >= 400 && status < 500;
  if (canRetry && !isClientError) {
    await new Promise((r) => setTimeout(r, 2000 + Math.random() * 3000));
    return fetchSockOdds(url, options, false);
  }
  console.error(`SockOdds request failed: ${status} ${payload?.error || error?.message}`);
  return null;
}
import random, time, requests

def fetch_sirenodds(url, headers, can_retry=True):
    try:
        r = requests.get(url, headers=headers); payload = r.json()
    except Exception as e:
        r, payload = None, None
    if payload and payload.get("success") is True:
        return payload["data"]
    status = r.status_code if r is not None else None
    if status == 429 and can_retry:
        time.sleep(int(r.headers.get("Retry-After", "5"))); return fetch_sirenodds(url, headers, False)
    client_error = payload and payload.get("success") is False and status and 400 <= status < 500
    if can_retry and not client_error:
        time.sleep(2 + random.random() * 3); return fetch_sirenodds(url, headers, False)
    print("SockOdds request failed:", status, (payload or {}).get("error"))
    return None
static JsonElement fetchSockOdds(String url, String key, boolean canRetry) throws Exception {
  var req = HttpRequest.newBuilder().uri(URI.create(url)).header("x-api-key", key).GET().build();
  var res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
  var payload = JsonParser.parseString(res.body()).getAsJsonObject();
  if (payload.has("success") && payload.get("success").getAsBoolean()) return payload.get("data");
  int status = res.statusCode();
  if (status == 429 && canRetry) { Thread.sleep(1000L * Long.parseLong(res.headers().firstValue("retry-after").orElse("5"))); return fetchSockOdds(url, key, false); }
  boolean clientError = status >= 400 && status < 500;
  if (canRetry && !clientError) { Thread.sleep(2000 + new Random().nextInt(3000)); return fetchSockOdds(url, key, false); }
  System.err.println("SockOdds request failed: " + status + " " + payload.get("error"));
  return null;
}
def fetch_sirenodds(url, key, can_retry: true)
  uri = URI(url); req = Net::HTTP::Get.new(uri); req["x-api-key"] = key
  res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
  payload = JSON.parse(res.body) rescue nil
  return payload["data"] if payload&.dig("success") == true
  status = res.code.to_i
  if status == 429 && can_retry
    sleep(res["retry-after"].to_i.nonzero? || 5); return fetch_sirenodds(url, key, can_retry: false)
  end
  client_error = payload&.dig("success") == false && status.between?(400, 499)
  if can_retry && !client_error
    sleep(2 + rand * 3); return fetch_sirenodds(url, key, can_retry: false)
  end
  warn "SockOdds request failed: #{status} #{payload&.dig('error')}"; nil
end
function fetchSockOdds(string $url, string $key, bool $canRetry = true) {
  $ch = curl_init($url); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["x-api-key: $key"], CURLOPT_TIMEOUT => 30]);
  $body = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
  $payload = $body !== false ? json_decode($body, true) : null;
  if (($payload['success'] ?? false) === true) return $payload['data'];
  if ($status === 429 && $canRetry) { sleep(5); return fetchSockOdds($url, $key, false); }
  $clientError = ($payload['success'] ?? null) === false && $status >= 400 && $status < 500;
  if ($canRetry && !$clientError) { usleep((2 + lcg_value() * 3) * 1000000); return fetchSockOdds($url, $key, false); }
  error_log("SockOdds request failed: $status " . ($payload['error'] ?? 'Unknown'));
  return null;
}
Need help?FAQ · Email · Contact