Skip to main content
Codon export takes the amino acid sequence of a variant and outputs a codon-optimized coding sequence (CDS) for your target expression host. Results are available as FASTA, CSV, or GenBank. Each variant in the batch costs 2 credits.

List available strategies

Strategies differ in their optimization objective (CAI maximization, GC content tuning, rare codon avoidance, cryptic splice site avoidance, etc.). Fetch the catalogue before submitting to pick the right one.
from kallima import KallimaClient

client = KallimaClient(api_key)

strategies = client.codon_exports.strategies()
for s in strategies:
    print(s["name"], "—", s["description"])

Submit a batch

One call submits one or more variants. The API returns a batch record with a job_id per variant.
batch = client.codon_exports.submit_batch(
    strategy="cai_max",
    host="cho",
    output_formats=["fasta", "genbank"],
    items=[
        {"variant_id": "var_aaa..."},
        {"variant_id": "var_bbb..."},
    ],
)

batch_id = batch["batch_id"]
job_ids = batch["job_ids"]    # one per variant, same order as items
export_ids = batch["export_ids"]  # one per variant
Supported hosts include cho, hek293, e_coli, pichia. Supported formats: fasta, csv, genbank.

Constraints

Every strategy applies the same set of sequence-level constraints on top of the chosen codons. Pass any of these in options on submit_batch; unset fields use the defaults below.
OptionTypeDefaultNotes
restriction_sitesstring[]["EcoRI","BamHI","HindIII","NdeI","XbaI","SalI","NotI","XhoI"]NEB common 6/8-cutters to avoid. Pick from the NEB common set.
gc_min / gc_maxfloat 0–10.40 / 0.60Global GC bounds across the full CDS.
gc_window_min / gc_window_maxfloat 0–10.30 / 0.70Bounds inside each sliding window.
gc_window_sizeint (nt)80Width of the sliding GC window.
repeat_kmer_sizeint (nt)9Flag any direct repeat at least this long. 0 disables.
check_splice_sitesbooltrueScan for cryptic splice donors / acceptors.
splice_score_thresholdfloat 0–10.80Normalized Shapiro-Senapathy score above which a site is flagged.
batch = client.codon_exports.submit_batch(
    strategy="cai_max",
    host="cho",
    output_formats=["fasta"],
    items=[{"variant_id": "var_aaa..."}],
    options={
        "restriction_sites": ["EcoRI", "BamHI", "NotI"],
        "gc_min": 0.42,
        "gc_max": 0.58,
        "check_splice_sites": True,
        "splice_score_threshold": 0.85,
    },
)

Cryptic splice sites

check_splice_sites runs a Shapiro-Senapathy PWM scan over the CDS and reports any donor or acceptor scoring at or above splice_score_threshold. Donors are scored against a 9-nt window with the invariant GT at +1/+2; acceptors against a 17-nt window (polypyrimidine tract + invariant AG at -2/-1). Hits land in export["violations"] with type="splice_site" and severity soft — they don’t block the export, but you should review them before cloning into a lentiviral or AAV vector, where cryptic splicing can truncate the transgene.
export = client.codon_exports.get(export_id)
for v in export["violations"]:
    if v["type"] == "splice_site":
        print(v["detail"])  # "Putative cryptic splice donor at position 312 (score 0.87). …"
The 0.80 default trades recall for precision — strong putative sites get flagged, weak motifs are ignored. Lower the threshold (e.g. 0.70) for AAV / lentiviral CAR-T workflows where a missed cryptic splice is more costly than extra review.

Poll for completion

import time

for job_id in job_ids:
    job = client.jobs.get(job_id)
    while job.status not in ("completed", "failed", "canceled"):
        time.sleep(10)
        job = client.jobs.get(job_id)
    print(job_id, job.status)

Download results

Once a job is complete, download the export for each variant:
for export_id in export_ids:
    export = client.codon_exports.get(export_id)
    if export["variable_cds"] is None:
        continue  # still running

    fasta_bytes = client.codon_exports.download(export_id, format="fasta")
    with open(f"{export_id}.fasta", "wb") as f:
        f.write(fasta_bytes)

    genbank_zip = client.codon_exports.download(export_id, format="genbank")
    with open(f"{export_id}.zip", "wb") as f:
        f.write(genbank_zip)
genbank format is returned as a ZIP archive containing one .gb file per chain.

Export record fields

export = client.codon_exports.get(export_id)

print(export["strategy"])              # "cai_max"
print(export["host"])                  # "cho"
print(export["constraints_satisfied"]) # bool — False if the optimizer hit hard constraints
print(export["violations"])            # list of unmet constraint descriptions
print(export["metrics"])               # dict — CAI, GC content, rare codon count, etc.

Add a signal peptide

Signal peptides are prepended to the CDS before optimization. The signal peptide catalogue lists built-in sequences plus any org-custom entries.
# Browse available signal peptides
for sp in client.codon_exports.signal_peptides():
    print(sp["id"], sp["name"])

# Attach per chain when submitting
batch = client.codon_exports.submit_batch(
    strategy="cai_max",
    host="cho",
    output_formats=["fasta"],
    items=[
        {
            "variant_id": "var_aaa...",
            "signal_peptides": {
                "H": "sp-uuid-for-heavy",
                "L": "sp-uuid-for-light",
            },
        }
    ],
)

Full pipeline example

import os, time
from kallima import KallimaClient

client = KallimaClient(os.environ["KALLIMA_API_KEY"])

variant_ids = ["var_aaa...", "var_bbb..."]
items = [{"variant_id": vid} for vid in variant_ids]

batch = client.codon_exports.submit_batch(
    strategy="cai_max",
    host="cho",
    output_formats=["fasta", "csv"],
    items=items,
)

for job_id, export_id in zip(batch["job_ids"], batch["export_ids"]):
    job = client.jobs.get(job_id)
    while job.status not in ("completed", "failed", "canceled"):
        time.sleep(10)
        job = client.jobs.get(job_id)

    if job.status != "completed":
        print(f"{job_id} failed")
        continue

    data = client.codon_exports.download(export_id, format="fasta")
    with open(f"{export_id}.fasta", "wb") as f:
        f.write(data)
    print(f"Saved {export_id}.fasta")