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 Generalist) alongside any custom models your org has trained.

3. Wait for it to finish

Segmentation runs asynchronously on GPU workers, so poll GET /predict/{prediction_id} until status is SUCCEEDED. The finished response carries the cell_count detected.
status moves through ENQUEUED (waiting for a GPU) → STARTED (running) → SUCCEEDED (or FAILED).

4. Export the results

Download the image’s result 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. If you predicted on one channel of a multiplex image, add that channel to the URL (?channel=2); the prediction response carries it as channel.
That’s the whole loop: upload → predict → export. 🎉

Optional: share the result

To show the result to someone who doesn’t use HalfPage, get a view-only link to the image. Anyone with the url sees the image with its latest cell outlines and counts in their browser, no account needed. See Sharing images.
curl

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, so 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, because 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.