Skip to main content
This walkthrough takes you through the full workflow with runnable curl and Python: upload an image (one call), run a prediction, wait for it, and download the resulting ROIs as GeoJSON — entirely over the API.

Before you start

1

Get an API key

Create one in the dashboard (Settings → API Keys) and export it:
See Authentication for details.
2

Install tooling (for the bash examples)

The curl snippets use jq to read JSON responses. The Python snippets use requests (pip install requests).

1. Upload your image

One request does everything: POST /upload streams the file in, creates the image record for you (named after the file), converts it, and returns the record already ready. No pre-registration, no polling.
Each image counts against your plan’s storage cap; POST /upload returns 402 once the cap is reached. Files can be up to 4 GB, but for anything larger than a few hundred MB — or a connection that might drop — use the resumable upload below.

2. Pick a model and run a prediction

List the models available to your organization, then run a prediction on your image. GET /models returns shared public base models (such as cpsam, the Cellpose-SAM generalist) alongside any custom models your org has trained.
Each organization runs one prediction at a time. If you already have one running, POST /predict returns 400 — wait for it to finish. If an identical prediction is already queued, the response comes back with status: "skipped" and the existing prediction_id.

3. Wait for it to finish

Segmentation runs asynchronously on GPU workers, so poll GET /predict/{prediction_id} until status is COMPLETED. The completed response carries the segmentation_id you’ll export, plus the cell_count detected.
status moves through SUBMITTEDSTARTEDCOMPLETED (or FAILED).

4. Export the results

Download the segmentation in whichever format you need. The overlay PNG is a presentation RGB image with masks composited over HalfPage’s normalized preview. It does not preserve original TIFF bit depth, microscopy metadata, or scientific display settings. GeoJSON is handy for GIS and web tools; the CSV is one row per cell; the ZIP is an ImageJ/FIJI ROI archive.
That’s the whole loop: upload → predict → export. 🎉

Large files: the resumable upload

For multi-GB files or unreliable connections, upload the pixels straight to object storage in chunks instead of through the API. It’s the same POST /upload endpoint — just send JSON ({name, size}) instead of a file. No bytes travel on that request; you get back presigned part URLs. PUT each chunk to its URL, call /complete, and poll until the image is ready. If a chunk fails, retry that one PUT; nothing else is lost.
The presigned PUT requests go straight to object storage — do not send your Authorization header on them. All other calls are authenticated with your API key as usual.
size must be the file’s exact byte size — the part plan is computed from it.
From here, continue at step 2 — everything downstream is identical.
The record counts against your storage cap from the moment it is created, and keeps counting until you delete it. If you abandon an upload, DELETE /upload/{image_id} frees the slot — it aborts anything still in flight and removes the record.

Full Python script

Next steps

API reference

Every endpoint, parameter, and response — with a live playground.

Using with AI agents

Point an agent at the MCP server and OpenAPI spec to drive this flow for you.