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

CodeHTTP statusMeaning
invalid_json400The request body is not valid JSON
validation_error400The request body, query, cursor, or route input is invalid
unauthorized401The API key is missing, malformed, expired, revoked, or invalid
insufficient_credits402The workspace does not have enough credits for the requested job
paid_plan_required402The requested action requires an active paid workspace plan
daily_limit_exceeded402The workspace reached a daily submission limit
concurrent_job_limit_exceeded402The workspace has too many active jobs
forbidden403The key is valid but lacks access or the required scope
user_not_found404The user associated with the API key no longer exists
team_not_found404The workspace associated with the API key no longer exists
not_found404The resource does not exist in the API key workspace
method_not_allowed405The route does not support the HTTP method
conflict409The request conflicts with the current resource state
job_not_completed409Results were requested before a job reached a result-ready state
payload_too_large413The request body is too large
unsupported_media_type415A JSON route was called without Content-Type: application/json
rate_limited429The request exceeded the public API rate limit
internal_error500The request failed unexpectedly

Handling errors

  • Retry rate_limited: Respect Retry-After and the rate-limit reset headers when present.
  • Retry transient internal_error responses carefully: Use Idempotency-Key when retrying job submissions.
  • Do not retry validation_error unchanged: Inspect the request shape, tool input contract, and field names.
  • Treat not_found as workspace-scoped: A job outside the API key workspace returns not_found.
  • Handle job_not_completed by waiting: Poll status or use the events endpoint before fetching results again. When Retry-After is 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}`);
  }
}