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();