Errors
All public API errors use one JSON envelope with a stable code and message.
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",
"details": {}
}
}The details field is included only when the route has structured details to return.
Error codes
| 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 |
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 |
paid_plan_required | 402 | The requested action requires an active paid workspace plan |
daily_limit_exceeded | 402 | The workspace reached a daily submission limit |
concurrent_job_limit_exceeded | 402 | The workspace has too many active jobs |
forbidden | 403 | The key is valid but 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 |
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. - 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.
JavaScript example
JavaScript
const response = await fetch("https://proteiniq.io/api/v1/jobs", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PROTEINIQ_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "fold-lysozyme-001",
},
body: JSON.stringify({
tool: "esmfold",
name: "Lysozyme ESMFold run",
input: {
inputs: [
{
id: "seqs_1",
slotId: "protein",
kind: "protein",
format: "fasta",
content: ">seq\nMKT...",
source: { type: "text" },
},
],
},
settings: {},
}),
});
const payload = await response.json();
if (!response.ok) {
switch (payload.error.code) {
case "rate_limited":
throw new Error("Wait before retrying");
case "validation_error":
throw new Error(`Fix request: ${payload.error.message}`);
default:
throw new Error(`${payload.error.code}: ${payload.error.message}`);
}
}