Python SDK

Use the Python SDK to list tools, manage workspace files, submit runs, wait for completion, and download result files.

The ProteinIQ Python SDK is a small client for the public /api/v1 API. It uses the same tool, job, result, and error models described in the API reference.

Install

Install the package from PyPI:

Bash
pip install proteiniq

For local development from this repository:

Bash
cd sdks/python
python -m pip install -e ".[dev]"

Authentication

The SDK reads PROTEINIQ_API_KEY and PROTEINIQ_BASE_URL from the environment. PROTEINIQ_BASE_URL is optional and defaults to https://proteiniq.io.

Bash
export PROTEINIQ_API_KEY="pq_live_abc123_your_secret"
export PROTEINIQ_BASE_URL="https://proteiniq.io"
Python
from proteiniq import ProteinIQ

client = ProteinIQ()

You can also pass credentials directly:

Python
client = ProteinIQ(api_key="pq_live_abc123_your_secret")

Submit and wait

Job input uses the canonical public API shape: input.inputs[]. Use client.tools.describe(tool_id) to inspect the required slots and settings for a tool before submitting.

Python
from proteiniq import ProteinIQ

client = ProteinIQ()

esmfold_input = {
    "inputs": [
        {
            "id": "seqs_1",
            "slotId": "protein",
            "kind": "protein",
            "format": "fasta",
            "content": ">lysozyme\nKVFGRCELAAAMKRHGLDNYRGYSLGNWVCAAKFESNFNTQATNRNTDGSTDYGILQINSR",
            "source": {"type": "text"},
        }
    ]
}

job = client.jobs.submit(
    tool="esmfold",
    name="Lysozyme ESMFold run",
    input=esmfold_input,
    settings={},
    idempotency_key="fold-lysozyme-001",
)

job = client.jobs.wait(job.id)
if job.status != "COMPLETED":
    raise RuntimeError(f"Job ended with status {job.status}: {job.error}")

result = client.results.get(job.id)
print(result.files)

client.jobs.wait() polls GET /api/v1/jobs/{jobId}/status and respects Retry-After when the API sends it.

Quote before submit

Use a quote to validate input and estimate credits without creating a job.

Python
quote = client.jobs.quote(
    tool="esmfold",
    input=esmfold_input,
    settings={},
)

print(quote.estimated_credits, quote.available_credits)

Tools

Use tool endpoints to discover valid tool ids and read the current input contract for a tool.

Python
tools = client.tools.list()
for tool in tools.data:
    print(tool.id, tool.name)

esmfold = client.tools.describe("esmfold")
print(esmfold.input)

The SDK keeps unknown response fields in each model's raw dictionary because tool-specific outputs can vary by tool.

Workspace files

Use client.files to upload, list, inspect, and delete saved workspace files. Uploaded files can be reused in later job inputs without sending their content again.

Python
uploaded = client.files.upload(
    "./protein.fasta",
    description="Example protein",
    tags=["protein", "test"],
)

files = client.files.list(format="FASTA", origin="UPLOAD", limit=10)
for file in files.data:
    print(file.id, file.filename, file.size)

file = client.files.get(uploaded.id)

Pass the returned file reference in input.inputs[].source when submitting or quoting a job:

Python
saved_file_input = {
    "inputs": [
        {
            "id": "protein_1",
            "slotId": "protein",
            "kind": "protein",
            "format": "fasta",
            "source": file.input_reference,
        }
    ]
}

job = client.jobs.submit(
    tool="esmfold",
    name="Fold saved protein",
    input=saved_file_input,
    settings={},
)

File references require jobs:write and files:read. Upload, list, get, and delete calls use the files:write or files:read scopes described in the Files API reference.

Download result files

Result responses include signed file URLs when files are available. The SDK downloads those files to a directory you choose.

Python
paths = client.results.download_files(job.id, "./outputs")

for path in paths:
    print(path)

Signed file URLs are temporary. Fetch the result again when a saved URL expires.

Error handling

API error envelopes map to typed SDK exceptions.

Python
from proteiniq.errors import ProteinIQError, RateLimitError, ValidationError

try:
    client.jobs.submit(tool="esmfold", name="Run", input=esmfold_input)
except RateLimitError as exc:
    print(f"Retry after {exc.retry_after} seconds")
except ValidationError as exc:
    print(f"Fix request shape: {exc.message}")
except ProteinIQError as exc:
    print(exc.code, exc.message, exc.details)

Branch on exc.code for API-specific behavior. Human-readable messages can change.