Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Quickstart (hosted API)

The hosted API runs CyteOnto for you at https://cyteonto.nygen.io. With the default models it needs no API key. A comparison is a job: you submit the labels, poll the job’s status, and download the results when it has finished. This page compares three author labels with the labels of two algorithms.

The curl examples use jq to read the JSON responses.

Submit the labels

Send the author labels and, for each algorithm, a list of labels of the same length. The labels at the same position are compared with each other.

curl
Python
export CYTEONTO_URL="https://cyteonto.nygen.io"

RUN_ID=$(curl -sS -X POST "$CYTEONTO_URL/compare" \
  -H 'Content-Type: application/json' \
  -d '{
    "authorLabels": ["alveolar macrophage", "regulatory T cell", "CD8-positive, alpha-beta T cell"],
    "algorithms": {
      "method_a": ["lung macrophage", "Treg", "CD8 T cell"],
      "method_b": ["alveolar mac", "T regulatory cell", "cytotoxic T cell"]
    }
  }' | jq -r .runId)
echo "$RUN_ID"

The response holds the run ID of the new job, in the form run-<uuid>, and its state:

{"runId": "run-<uuid>", "state": "queued"}

Keep the run ID: you need it for every other request about the job.

Wait for the job

Poll /status/<run ID> until the state is completed or failed. A job normally moves from queued to running and ends in one of these two states, but a job that stops unexpectedly can keep its last state, so stop polling after a time limit.

curl
Python
# Poll every 10 seconds, for at most an hour.
for _ in $(seq 360); do
  STATE=$(curl -sS "$CYTEONTO_URL/status/$RUN_ID" | jq -r .state)
  echo "$STATE"
  if [ "$STATE" = completed ] || [ "$STATE" = failed ]; then break; fi
  sleep 10
done

The status also counts the labels and the result rows, and records which models served the job:

{
  "runId": "run-<uuid>",
  "state": "completed",
  "createdAt": "<UTC timestamp>",
  "startedAt": "<UTC timestamp>",
  "completedAt": "<UTC timestamp>",
  "error": null,
  "numAuthorLabels": 3,
  "numAlgorithms": 2,
  "numRows": 6,
  "resultCsvPath": "user_files/run-<uuid>/result.csv",
  "resultJsonPath": "user_files/run-<uuid>/result.json",
  "modelPairUsage": {
    "llmTier": "primary",
    "embeddingTier": "primary",
    "llmProvider": "nebius",
    "llmModel": "moonshotai/Kimi-K2.6",
    "embeddingProvider": "nebius",
    "embeddingModel": "Qwen/Qwen3-Embedding-8B"
  }
}

Download the results

Fetch the results as JSON, a list with one object per row, or as a CSV file:

curl
Python
curl -sS "$CYTEONTO_URL/result/$RUN_ID?format=json" | jq
curl -sS "$CYTEONTO_URL/result/$RUN_ID?format=csv" -o "$RUN_ID.csv"

There is one row for each algorithm and position, six here. The main columns are:

ColumnMeaning
algorithm, pair_indexThe algorithm and the position of the label pair, from 0
author_label, algorithm_labelThe two labels, lowercased
author_ontology_id, algorithm_ontology_idThe Cell Ontology term that each label matched, such as CL:0000815
author_ontology_name, algorithm_ontology_nameThe names of those terms
cytescore_similarityThe similarity of the two terms: 1 for the same term, and lower the less related they are
similarity_methodHow the row was scored, such as cytescore, or why it was not, such as partial_match

Read the results explains every column and how to interpret the scores.

Next steps