Errors
Identify failed requests and choose the next action.
ProteinIQ API errors use a consistent JSON envelope. Clients should branch on error.code, not on the human-readable message.
Error envelope
JSON
{
"error": {
"code": "validation_error",
"message": "Invalid request data",
"resolution": "Correct the request using the OpenAPI contract and error.details when present, then retry.",
"details": {}
}
}The resolution field gives a short next action for the error code. The details field is included only when the route has structured details to return.
Common error codes
These codes cover shared API failures. Workflow and other routes can return additional operation-specific codes; read resolution and details when present.
| Code | HTTP status | Meaning |
|---|---|---|
invalid_json | 400 | The request body is not valid JSON |
validation_error | 400 | The request body, query, cursor, or route input is invalid. Job input errors include the rejected path and the canonical input format. |
unauthorized | 401 | The API key is missing, malformed, expired, revoked, or invalid |
insufficient_credits | 402 | The workspace does not have enough credits for the requested job |
daily_limit_exceeded | 402 | The workspace reached a daily submission limit |
concurrent_job_limit_exceeded | 402 | The workspace has too many active jobs |
paid_plan_required | 402 | The workspace plan does not include the requested API operation |
forbidden | 403 | The workspace plan does not include API access, or the key lacks access or the required scope |
user_not_found | 404 | The user associated with the API key no longer exists |
team_not_found | 404 | The workspace associated with the API key no longer exists |
not_found | 404 | The resource does not exist in the API key workspace |
method_not_allowed | 405 | The route does not support the HTTP method |
conflict | 409 | The request conflicts with the current resource state |
price_changed | 409 | The current fixed charge or initial runtime reservation exceeds max_quoted_credits. Review a fresh quote and submit with a new idempotency key. |
job_not_completed | 409 | Results were requested before a job reached a result-ready state |
payload_too_large | 413 | The request body is too large |
unsupported_media_type | 415 | A JSON route was called without Content-Type: application/json |
rate_limited | 429 | The request exceeded the public API rate limit |
internal_error | 500 | The request failed unexpectedly |
Handling errors
- Retry
rate_limited: RespectRetry-Afterand the rate-limit reset headers when present. - Retry transient
internal_errorresponses carefully: UseIdempotency-Keywhen retrying job submissions. - Do not retry
validation_errorunchanged: Inspect the request shape, tool input contract, and field names. - Rebuild rejected job inputs: Follow the tool input model. Each entry needs
id,slotId,kind,format, andsource, pluscontentor a supported saved-file reference. Mixed current and retired fields are rejected. - Treat
not_foundas workspace-scoped: A job outside the API key workspace returnsnot_found. - Handle
job_not_completedby waiting: Poll status or use the events endpoint before fetching results again. WhenRetry-Afteris present, wait that many seconds before retrying the result endpoint. - Use
resolutionfor the next action: Display or log the field when an automated client cannot recover without changing the request or workspace state.
Inspect an error
This read-only example checks the response before using account data:
JavaScript
const response = await fetch("https://proteiniq.io/api/v1/account", {
headers: {
Authorization: `Bearer ${process.env.PROTEINIQ_API_KEY}`,
},
});
const payload = await response.json();
if (!response.ok) {
const { code, message, resolution, details } = payload.error;
console.error({ code, message, resolution, details });
if (code === "rate_limited") {
console.error("Retry-After:", response.headers.get("Retry-After"));
}
throw new Error(`${code}: ${message}`);
}
console.log(payload.workspace);Do not log the API key or private request contents when reporting an error. For an uncertain job submission, retain its exact payload and idempotency key before retrying.