Python client for the Strand Platform — H&E → multiplex protein inference.
Agent-friendly docs: The full API reference is published as Markdown at https://app.strandai.com/docs/api.md, and the LLM index lives at https://app.strandai.com/llms.txt.
pip install strand-sdk
# or with bioinformatics extras (AnnData / zarr):
pip install "strand-sdk[anndata]"If your environment can't reach PyPI, you can install directly from the repository as a fallback:
pip install "git+https://github.com/Strand-AI/strand-sdk-python.git"One blocking call runs the full pipeline — upload, submit, wait, download:
from strand import Client
client = Client(api_key="sk-strand-...")
result = client.predict(
"biopsy.ome.tiff",
markers=["HER2", "CD8", "PD1"],
output_dir="./outputs/",
)
print(f"Used {result.credits_used} credits; wrote {len(result.marker_outputs)} markers")client.predict(...) returns a PredictResult with job_id, status,
credits_used, marker_outputs (paths under output_dir), and results
(a JobResults handle for selective reads). It raises JobFailedError if the
job fails, JobTimeoutError if the deadline elapses, and surfaces
InsufficientCreditsError / RateLimitError on submit issues.
Pass on_progress=lambda stage, frac: ... to follow the four stages
("upload", "submit", "wait", "download").
client.predict is also a namespace, so the underlying steps stay available
for fine-grained control:
upload = client.uploads.upload_file("slide.svs")
estimate = client.predict.estimate(upload.id, markers=["CD3", "CD8", "Ki67"])
print(f"Will cost ≈ {estimate.estimated_credits} credits")
job = client.predict.submit(upload.id, markers=["CD3", "CD8", "Ki67"])
job.wait() # blocks until terminal status
adata = job.download_results() # AnnData| Source | Variable / argument | Default |
|---|---|---|
| Env | STRAND_API_KEY |
required |
| Env | STRAND_BASE_URL |
https://app.strandai.com |
| Arg | Client(api_key=..., base_url=..., timeout=..., max_retries=...) |
— |
src/strand/
__init__.py public surface re-exports
_client.py Client (top-level)
_uploads.py uploads namespace (incl. resumable chunked upload helper)
_predict.py predict namespace — `client.predict(...)` (full pipeline) + `.estimate` / `.submit`
_jobs.py Job (wait / stream_events / download_results)
_results.py OME-Zarr v3 download + AnnData conversion
_models.py user-facing snake_case dataclasses
_http.py internal httpx wrapper with typed error mapping
_errors.py typed exceptions
openapi.json pinned snapshot of the platform spec (drift-check)
Transport is hand-written for ergonomic snake_case fields and AnnData integration. To check the SDK against an updated spec:
# regenerate a reference client and diff the request/response surface
uv tool run --from "openapi-python-client>=0.21" --with "click<8.2" \
openapi-python-client generate \
--path openapi.json \
--output-path /tmp/strand-sdk-ref \
--meta none --overwriteTo refresh openapi.json itself against a live server:
curl https://app.strandai.com/api/v1/openapi.json -o openapi.json
# or against local dev:
# curl http://localhost:3000/api/v1/openapi.json -o openapi.jsonuv sync --all-extras
uv run pytest
uv run ruff check src tests
uv run mypy srcFile bug reports and feature requests at Strand-AI/strand-sdk-python/issues.
We don't accept external pull requests on the SDK at this time. If you'd like to contribute or have ideas you'd like to discuss, email support@strandai.com.
Apache 2.0