Error Codes
All error codes returned by the UpVoot platform and how to handle them.
HTTP errors (on WebSocket upgrade)
| Status | Code | Cause | Resolution |
|---|---|---|---|
400 | INVALID_KEY_FORMAT | API key does not match expected format | Ensure the key starts with sk_live_ and is 72 characters total |
401 | KEY_NOT_FOUND | No key with this hash exists | Generate a new key from the dashboard |
402 | INSUFFICIENT_BALANCE | Account has 0 points | Purchase more points from the billing page |
403 | KEY_REVOKED | Key has been revoked | Generate a replacement key |
404 | AGENT_NOT_FOUND | Agent associated with this key was deleted | Create a new agent and generate a new key |
429 | RATE_LIMITED | Too many concurrent connections from this account | Reduce concurrent calls or contact support for higher limits |
500 | PLATFORM_ERROR | Internal platform error | Retry after 5 seconds; report persistent errors to support |
Runtime JSON error messages
These are sent as JSON text frames during an active call when a recoverable error occurs. The connection remains open unless noted.
| code | Meaning | Connection |
|---|---|---|
STT_ERROR | Speech-to-text processing failed for this chunk | Stays open — next audio chunk is retried |
LLM_TIMEOUT | Language model took too long to respond | Stays open — agent says a brief fallback phrase |
TTS_ERROR | Voice synthesis failed | Stays open — retried on next turn |
BALANCE_EXHAUSTED | Points ran out mid-call | Closed after call_end message |
MAX_TURNS_REACHED | Agent hit configured turn limit | Closed after call_end message |
Recommended retry policy
const MAX_RETRIES = 3;
const RETRY_DELAY_MS = [1000, 2000, 5000]; // exponential backoff
async function connectWithRetry(apiKey: string, attempt = 0): Promise<WebSocket> {
try {
const ws = new WebSocket(`wss://api.upvoot.com/voice/${apiKey}`);
await new Promise<void>((resolve, reject) => {
ws.onopen = () => resolve();
ws.onerror = () => reject(new Error("Connection failed"));
});
return ws;
} catch (err) {
if (attempt >= MAX_RETRIES) throw err;
await new Promise((r) => setTimeout(r, RETRY_DELAY_MS[attempt]));
return connectWithRetry(apiKey, attempt + 1);
}
}Do not retry on 401, 402, 403, or404 — these indicate a configuration problem, not a transient failure.