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.

Usage limits and quotas

CyteType is free for academic and non-commercial research within the limits on this page. Personal accounts have rolling job limits; organizations have a cluster quota set by their license. A few technical limits apply to everyone. The Account page shows how much you have left.

Personal accounts

Jobs submitted with a personal API key (cyt_p_...) count toward three rolling windows:

WindowJobs
Last 24 hours10
Last 7 days50
Last 30 days100

The windows roll: a job stops counting 24 hours, 7 days or 30 days after you submitted it. When you reach a limit, the error tells you which window is full and roughly when it frees up.

What counts:

What does not count:

Organizations

Jobs submitted with an organization API key (cyt_...) count toward the organization’s cluster quota:

The Account page in the organization workspace shows the clusters annotated in the current period and the clusters remaining.

Per-key quotas

Any API key, personal or organization, can have its own Quota limit: the maximum number of clusters that jobs submitted with the key can contain, over the key’s lifetime. Running and completed jobs count, including deleted ones; failed jobs do not. A key quota applies in addition to your personal limits or your organization’s quota.

You set quotas on your personal keys yourself. Organization admins set them on organization keys, for example to give each member or pipeline a share of the organization’s quota. See Dashboard.

When limits are checked

The clients upload your data files before they submit the job:

  1. When an upload starts, the server checks that your API key is valid and active and that its organization’s license has not expired.

  2. When the job is submitted, after the upload, the server checks your personal limits, the key’s quota, the organization’s quota and the requested visibility.

A job refused at step 2 does not run, and its upload is lost: you upload again when you resubmit. Before submitting a large dataset, check the Account page. Organization visibility needs a key with an organization license; when you request it with a key that looks like a personal key (cyt_p_...), both clients warn before the upload.

Data and upload limits

FileMaximum size
obs.duckdb (cell metadata)2 GiB (2,147,483,648 bytes)
vars.h5 (expression matrix)50 GiB (53,687,091,200 bytes)

Both clients check the file sizes before uploading. A file that is too large stops the run with an error that names the file (“exceeds upload limit”); in Python it is a ValueError. With require_artifacts=False, the job continues without that file (CyteTypeR without either file), and features that need it (cell-level queries in Chat and MCP, cell-level differential expression, target analysis) are unavailable for the job. Large datasets explains how to reduce the file sizes.

An uploaded file expires if no job uses it within 24 hours. The clients submit the job right after uploading and upload again on every run, so you do not need to act on this.

Job limits

LimitValue
Marker genes used per cluster250 (any more are ignored)
n_parallel_clusters1 to 50; used only with your own LLM
Server time limit per job4 hours; the job is then stopped and reported as failed
Client wait (timeout_seconds)7,200 seconds (2 hours) by default
Target analysis run3 hours

When the client stops waiting, Python raises CyteTypeTimeoutError and CyteTypeR stops with an error of class cytetype_timeout_error that names the job. The job keeps running on the server. Fetch the results later with get_results() in Python or GetResults(job_id = ...) in R (see Run, monitor and rerun jobs).

Chat limits

LimitValue
Runs attached to a conversation10
Clusters selected per message12
Outputs attached to a message12
Message length16,000 characters
Answers running at the same time1 per account, across all conversations
Time per answer10 minutes waiting to start, 30 minutes running
Outputs created per answer12
Rows per table500
Conversations100 per account
Messages per conversation100, including stopped and failed ones

When you reach one of these limits, Chat tells you what to do:

SituationMessage
Another answer is running“Another Chat turn is still running. Open that conversation or wait for it to finish.”
100 conversations“You have reached the saved-conversation limit. Delete an older conversation before starting another.”
100 messages in a conversation“This conversation has reached its turn limit. Start a new conversation to continue.”
An answer waited or ran too long“The turn exceeded its execution window. Please retry.”, “The chat turn exceeded its execution deadline.” or “The Chat turn exceeded its time limit.”
An answer gathered too much data“This turn gathered more tool output than the model can read at once. Ask a narrower question or split it into smaller steps.”

See Chat.

MCP connector limits

LimitValue
Connected jobs10 per signed-in user and AI client
Connected jobs forgotten after12 hours without a tool call that uses them
Cell-level differential expression20 runs per hour per user
Label comparison (compare_labels_cyteonto)10 requests per hour per user
Rows per metadata query200
Genes per expression lookup30 (lookup_gene_expression), 10 (summarize_gene_expression)
Groups per expression summaryThe 40 largest groups, with up to 5,000 sampled cells per group
Cells per group in cell-level differential expression5,000 (larger groups are subsampled)
Genes per direction in differential expression1 to 100
Embedding points2,000 by default, at most 5,000
Target candidates per ranking10 by default, at most 25
Sign-inRenewed automatically while in use; sign in again after 6 days without use

When an hourly limit is reached, the tool returns a message such as “Rate limit reached: at most 20 differential expression runs on cell-level data per hour. Try again in about 12 minute(s).” See Connect AI assistants (MCP).

Errors when you reach a limit

SituationError codePython exceptionMessage
Personal limit reachedRATE_LIMIT_EXCEEDEDRateLimitError“Daily limit reached (10/10). Resets in about 3 hours. For a free academic license with higher limits, email contact@nygen.io” (“Weekly” and “Monthly” for the other windows)
Organization quota too small for the jobQUOTA_EXCEEDEDQuotaExceededError“Quota exceeded: This job requires 24 clusters but you only have 10 remaining (990/1000 used). Please contact your organization admin”
Key quota too small for the jobQUOTA_EXCEEDEDQuotaExceededErrorThe same message, without the last sentence
Organization license expiredLICENSE_EXPIREDAuthorizationError“License has expired. Please contact your organization admin(s): ...”
Key disabledTOKEN_INACTIVEAuthenticationError“API token has expired or been deactivated”
Organization visibility with a key without an organization license, such as a personal keyHTTP_ERRORAPIError“Org visibility requires an organization license”
Upload file too large(checked by the client)ValueError“... exceeds upload limit: ...”
Job stopped after 4 hours(job status)JobFailedError“Job ... failed”
Client stopped waiting(checked by the client)CyteTypeTimeoutError“Job ... did not complete within ...s”

The numbers in the messages are examples. The CyteType exceptions have .error_code and .message attributes and can be imported from cytetype:

Python
R
from cytetype import QuotaExceededError, RateLimitError

try:
    adata = annotator.run(study_context="Human PBMC from a healthy donor")
except RateLimitError as err:
    print(err.error_code)  # RATE_LIMIT_EXCEEDED
    print(err.message)     # which window is full and when it frees up
except QuotaExceededError as err:
    print(err.message)     # clusters required and clusters remaining

In R, a refused submission stops with a message that starts with “Job submission failed:” and includes the error code in square brackets, for example [QUOTA_EXCEEDED]. A personal-limit error shows the server’s message directly, followed by a reminder that the limits apply to every job, including jobs that use your own LLM. Errors and error codes lists every error.

Get more capacity