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.

HTTP API

The hosted API runs comparisons at https://cyteonto.nygen.io. Requests and responses are JSON. The service also serves interactive documentation at /docs and its OpenAPI schema at /openapi.json.

Method and pathPurpose
POST /compareSubmit a comparison job
GET /status/{runId}Get the state of a job
GET /result/{runId}Download the results of a completed job
GET /healthCheck that the service is up

A job runs in the background: submit it, poll its status until it is completed or failed, then download the results. The hosted API quickstart shows these steps with curl and Python.

POST /compare

Submit the author labels and the labels of one or more algorithms. Only authorLabels and algorithms are required; the other fields select the models and the options of the comparison, as the arguments of CyteOnto.compare() do in Python.

FieldTypeDefaultDescription
authorLabelsarray of stringsRequiredThe author labels, one per item. Must not be empty
algorithmsobjectRequiredMaps each algorithm’s name to its labels, one per author label, in the same order. Needs at least one algorithm; author is not a valid name
llmProviderstringnebiusThe LLM provider: nebius, fireworks, openrouter, together or openai
llmModelstringmoonshotai/Kimi-K2.6The LLM, as the provider names it
llmApiKeystring or nullnullYour API key for llmProvider. When omitted, the service uses its own key for the provider, and the job fails if it has none
embeddingProviderstringnebiusThe embedding provider: nebius, deepinfra, fireworks, google, openai, openrouter or together
embeddingModelstringQwen/Qwen3-Embedding-8BThe embedding model, as the provider names it
embeddingApiKeystring or nullnullYour API key for embeddingProvider. When omitted, the service uses its own key for the provider, and the job fails if it has none
embeddingModelSettingsobject or nullnullFields added to each embedding request body, for openrouter only. null routes OpenRouter requests to DeepInfra first, and {} sends no routing
embeddingMaxConcurrentinteger, at least 1100Maximum number of embedding requests at the same time
maxDescriptionConcurrencyinteger, at least 1100Maximum number of LLM requests at the same time
usePubmedToolbooleanfalseLet the LLM search PubMed while it describes a label
reasoningbooleanfalseLeave the model’s reasoning as the provider sets it; when false, the requests ask the provider to turn it off
metricstringcosine_kernelThe similarity metric
metricParamsobject or nullnullThe center, width and amplitude of cosine_kernel
minMatchSimilaritynumber, 0 to 10.1The match threshold
compoundScoringstringmaxHow compound labels are scored: max or hungarian_mean
useCachebooleantrueReuse the caches of the run. Each job has a new run ID, so this only reuses the splits of labels that the authors and the algorithms of the job share

The default models match the precomputed ontology files. With another LLM or embedding model, the job first describes or embeds the 2,902 Cell Ontology terms for that model pair, which takes much longer. The service calls the LLM through the provider’s OpenAI-compatible API. If descriptions fail, the service retries them with its fallback LLM, Kimi K2.6 on Fireworks, and the status reports it. It also falls back to Qwen3-Embedding-8B on OpenRouter when embeddings fail; the first job that does so also embeds the 2,902 ontology descriptions with that model, which takes longer. The schema also accepts ollama as embeddingProvider, but the service has no Ollama server: each such job first tries to reach it for every ontology term and then switches to the fallback model, so do not use it with the hosted API. See Choose the embedding provider.

The response holds the new job’s run ID:

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

Request options

Options go in the same body as the labels. This request scores compound labels with hungarian_mean, leaves weak matches unmatched and widens the kernel of the metric:

curl -sS -X POST "https://cyteonto.nygen.io/compare" \
  -H 'Content-Type: application/json' \
  -d '{
    "authorLabels": ["AT2 cell-plasma cell doublet", "regulatory T cell"],
    "algorithms": {"method_a": ["plasma cell", "Treg"]},
    "compoundScoring": "hungarian_mean",
    "minMatchSimilarity": 0.5,
    "metricParams": {"width": 0.5}
  }'

To send your own API keys, build the body with jq, which quotes the values of shell variables correctly. Inside the single quotes of -d '...', the shell would send $NEBIUS_API_KEY as literal text:

jq -n --arg key "$NEBIUS_API_KEY" '{
  authorLabels: ["alveolar macrophage", "regulatory T cell"],
  algorithms: {method_a: ["lung macrophage", "Treg"]},
  llmApiKey: $key,
  embeddingApiKey: $key
}' | curl -sS -X POST "https://cyteonto.nygen.io/compare" \
  -H 'Content-Type: application/json' -d @-

GET /status/{runId}

Returns the state of a job.

FieldTypeDescription
runIdstringThe run ID
statestringqueued, running, completed or failed
createdAtstringWhen the job was submitted, as an ISO 8601 UTC timestamp
startedAtstring or nullWhen the job started
completedAtstring or nullWhen the job completed or failed
errorstring or nullFor a failed job, the exception that stopped it, as <ExceptionClass>: <message>
numAuthorLabelsintegerThe number of author labels
numAlgorithmsintegerThe number of algorithms
numRowsinteger or nullFor a completed job, the number of result rows
resultCsvPathstring or nullFor a completed job, the path of the CSV result on the service’s storage
resultJsonPathstring or nullFor a completed job, the path of the JSON result on the service’s storage
modelPairUsageobject or nullOnce the job has run: llmTier, primary, or mixed when the fallback LLM was asked to describe labels; embeddingTier, the models that made the label embeddings that were matched, primary, fallback, or mixed for both; and the llmProvider, llmModel, embeddingProvider and embeddingModel. When a tier is not primary, its fields name the fallback model

A job normally moves from queued to running and ends as completed or failed. A job that stops unexpectedly can keep its last state, so stop polling after a time limit.

GET /result/{runId}

Returns the results of a completed job. The format query parameter selects the format:

Both have the columns described in Read the results.

GET /health

Returns {"ok": true} when the service is up.

Errors

Errors are JSON objects with a detail field.

StatusWhen
400POST /compare: authorLabels or algorithms is empty, or an algorithm’s labels differ in number from the author labels. GET /result: format is neither json nor csv
404No job has this run ID
409GET /result: the job has not completed
422POST /compare: the body does not match the schema, such as a missing required field, an unknown field, a value of the wrong type, or a value out of range; detail lists the problems
500GET /result: the result of a completed job is missing

Other problems show up while the job runs. A job fails, with the reason in error, for example when an algorithm is named author, when no API key is available for a provider, or when the labels cannot be embedded. The service does not check your API keys when you submit a job. If the provider rejects an LLM key, the fallback LLM may describe the labels instead and the job completes, so check modelPairUsage.

Privacy

The service has no accounts: anyone who has a run ID can read the job’s status and results. Run IDs are random, but share them only with people who may see your labels. The service sends your labels to the LLM and embedding providers of the job, and may send them to its fallback providers, Fireworks and OpenRouter, even when you select others. With usePubmedTool, the model’s search terms go to NCBI. The service keeps the status, the results and the label splits, descriptions and embeddings of each job.