Skip to main content

Errors

Every error response has the same shape:

{
"statusCode": 400,
"error": "Bad Request",
"message": "name must be a string"
}

message is a string for most errors, but an array of strings for validation errors that fail on more than one field at once:

{
"statusCode": 400,
"error": "Bad Request",
"message": ["name must be a string", "firstMessage must be a string"]
}

Always handle both shapes — check whether message is an array before treating it as a single string, or just .join(', ') it either way.

Status codes you'll actually see

CodeMeaningTypical cause
400Bad RequestA required field is missing, or fails validation
401UnauthorizedMissing, invalid, expired, or revoked credentials
404Not FoundThe id doesn't exist — or belongs to another org
429Too Many RequestsYou've hit a rate limit

Why cross-tenant access looks like 404, not 403

If you request a resource (an agent, a call, a campaign) that belongs to a different organization, you get 404 Not Found — the same response as if the id genuinely didn't exist anywhere. This is deliberate: a 403 Forbidden would confirm "this id exists, you're just not allowed to see it," which leaks information about other tenants' data. 404 reveals nothing either way.

If you're debugging a mysterious 404 for an id you're sure is correct, double-check you're using the API key (or session) for the organization that actually owns it.

Example: handling errors in a client

const res = await fetch('https://convostack.ai/api/agents', {
headers: { Authorization: `Bearer ${apiKey}` },
});

if (!res.ok) {
const body = await res.json();
const message = Array.isArray(body.message) ? body.message.join(', ') : body.message;
throw new Error(`ConvoStack API error (${res.status}): ${message}`);
}

const agents = await res.json();