SDK Tutorial

Customer walkthrough for using `OmClient` with Generated Data, diligence workflows, Hub jobs, Molecule Fulfillment, jobs, and data loading.

Install and authenticate

Install packagesBash
pip install omtx
Set API key and run a smoke testBash
export OMTX_API_KEY="omtx_..."
python - <<'PY'
from omtx import OmClient

with OmClient() as client:
    print(client.status())
    print(client.users.profile())
PY

Generated Data catalog visibility

Read Generated Data contextPython
from omtx import OmClient

with OmClient() as client:
    models = client.models.catalog(limit=5)
    catalog = client.datasets.catalog()

print("Model count:", models["count"])
print("Generated Data rows:", catalog["data_generated"]["count"])
print("Generated Data protein UUIDs:", catalog["accessible_generated_protein_uuids"][:5])

Customer use cases

  • Generated Data visibility: render data_generated.items[] plus accessible_generated_protein_uuids[] for Generated Data proteins available now.
  • Generated Data access checks: use accessible_generated_protein_uuids[] to confirm which proteins are available to your account.
  • Access control: request shard exports only for Generated Data tied to qualifying Data Generation output.

Load dataframes from protein UUID

Combined loading for model training (single call)Python
from omtx import OmClient

with OmClient() as client:
    loaded = client.load_data(
        protein_uuid="YOUR_GENERATED_PROTEIN_UUID",
        binders=50000,
        nonbinder_multiplier=5,
        sample_seed=42,
    )

binders = loaded["binders"]
nonbinders = loaded["nonbinders"]
print("Binder rows:", len(binders))
print("Non-binder rows:", len(nonbinders))
binders.show(top_n=24)  # defaults: smiles + binding_score
Separate pool loading for explicit controlPython
from omtx import OmClient

with OmClient() as client:
    binders = client.load_binders(
        protein_uuid="YOUR_GENERATED_PROTEIN_UUID",
        n=1000,
        sample_seed=42,
    )
    nonbinders = client.load_nonbinders(
        protein_uuid="YOUR_GENERATED_PROTEIN_UUID",
        n=10000,
        sample_seed=42,
    )
# Omit n (or set n=None) to load the full pool.

print("Binder rows:", len(binders))
print("Non-binder rows:", len(nonbinders))
print("Binder columns:", binders.columns)
# show() renders inline in notebooks; no extra display() wrapper needed.
binders.show(top_n=24)  # defaults: smiles + binding_score
binders.show(top_n=24, sort_by="selectivity_score")
Manual shard export (advanced)Python
from omtx import OmClient

with OmClient() as client:
    urls = client.binders.urls(
        protein_uuid="YOUR_GENERATED_PROTEIN_UUID",
    )

print("URLs expire at:", urls["expires_at"])
print("Binder shard count:", len(urls["binder_urls"]))
print("Non-binder shard count:", len(urls["non_binder_urls"]))
print("First binder URL:", urls["binder_urls"][0])

Run diligence workflows

Search, gather, and crawl (asynchronous)Python
from omtx import OmClient

with OmClient() as client:
    search_job = client.diligence.search(query="PARP inhibitor resistance mechanisms")
    gather_job = client.diligence.gather(
        query="EGFR inhibitor clinical evidence",
        preset="quick",
    )
    crawl_job = client.diligence.crawl(
        url="https://example.org/egfr-review",
        preset="quick",
    )

    search_result = client.jobs.wait(search_job["job_id"], poll_interval=5, timeout=1800)
    gather_result = client.jobs.wait(gather_job["job_id"], poll_interval=5, timeout=1800)
    crawl_result = client.jobs.wait(crawl_job["job_id"], poll_interval=5, timeout=1800)

print("Search status:", search_result["status"])
print("Gather status:", gather_result["status"])
print("Crawl status:", crawl_result["status"])
Deep diligence and report synthesisPython
from omtx import OmClient

with OmClient() as client:
    dd_job = client.diligence.deep_diligence(
        query="BRAF inhibitor resistance landscape",
        preset="quick",
    )
    dd_result = client.jobs.wait(
        dd_job["job_id"],
        result_endpoint="/v2/jobs/deep-diligence/{job_id}",
        poll_interval=5,
        timeout=1800,
    )

    synth_job = client.diligence.synthesize_report(gene_key="brd4")
    synth_result = client.jobs.wait(
        synth_job["job_id"],
        result_endpoint="/v2/jobs/synthesizeReport/{job_id}",
        poll_interval=5,
        timeout=1800,
    )

print("Deep diligence claims:", dd_result["result"]["total_claims"])
print("Synthesis keys:", list(synth_result.keys()))

Fulfill molecules

Search, quote, and invoice OnePot-backed moleculesPython
from omtx import OmClient

with OmClient() as client:
    pricing = client.molecules.pricing()
    hits = client.molecules.search(
        smiles_list=["CC(=O)Oc1ccccc1C(=O)O"],
        max_results=5,
    )
    quote = client.molecules.quote(
        items=[{"smiles": "CC(=O)Oc1ccccc1C(=O)O", "quantity": 1}],
    )
    invoice = client.molecules.checkout(
        items=[{"smiles": "CC(=O)Oc1ccccc1C(=O)O", "quantity": 1}],
        shipping_address_id="addr_123",
    )

print("Provider:", pricing["provider"])
print("Search response keys:", list(hits.keys()))
print("Quote total cents:", quote["total_amount_cents"])
print("Order number:", invoice["order_number"])

Function map for API-key users

Available SDK functionsPython
from omtx import OmClient

with OmClient() as client:
    # Health and account
    client.status()
    client.users.profile()
    # Wallet funding is explicit only:
    # confirmation = client.wallet.expected_topup_confirmation(amount_cents=12500, payment_mode="saved_card")
    # client.wallet.topup(amount_cents=12500, payment_mode="saved_card", user_approval_confirmation=confirmation, idempotency_key="wallet-topup-demo-001")

    # Generated Data and shard exports
    client.models.catalog(limit=5)
    client.datasets.catalog()
    client.load_data(
        protein_uuid="YOUR_GENERATED_PROTEIN_UUID",
        binders=1000,
        nonbinder_multiplier=5,
        sample_seed=42,
    )
    client.load_binders(
        protein_uuid="YOUR_GENERATED_PROTEIN_UUID",
        n=1000,
        sample_seed=42,
    ).show(top_n=24)  # default columns: smiles + binding_score
    client.load_nonbinders(
        protein_uuid="YOUR_GENERATED_PROTEIN_UUID",
        n=10000,
        sample_seed=42,
    )
    client.binders.urls(
        protein_uuid="YOUR_GENERATED_PROTEIN_UUID",
    )

    # Data Generation order creation
    sequences = [{"name": "target", "sequence": "M" * 120}]
    client.data_generation.quota_order(
        sequences=sequences,
        idempotency_key="dg-quota-target-001",
    )
    client.data_generation.invoice_order(
        sequences=sequences,
        idempotency_key="dg-invoice-target-001",
    )

    # Diligence workflows
    client.diligence.search(query="example")
    client.diligence.gather(query="example", preset="quick")
    client.diligence.crawl(url="https://example.org", preset="quick")
    client.diligence.deep_diligence(query="example", preset="quick")
    client.diligence.synthesize_report(gene_key="brd4")
    client.diligence.list_gene_keys()

    # Artifacts and Hub workflows
    client.artifacts.upload("target.pdb")
    client.artifacts.get("artifact-id")
    client.hub.submit(
        job_type="hub.diffdock",
        payload={
            "protein_artifact_id": "artifact-id",
            "ligand_smiles": "CCO",
        },
    )
    client.hub.diffdock(
        protein_artifact_id="artifact-id",
        ligand_smiles="CCO",
    )

    # Molecule Fulfillment
    client.molecules.pricing()
    client.molecules.search(
        smiles_list=["CC(=O)Oc1ccccc1C(=O)O"],
        max_results=5,
    )
    client.molecules.quote(
        items=[{"smiles": "CC(=O)Oc1ccccc1C(=O)O", "quantity": 1}]
    )
    client.molecules.checkout(
        items=[{"smiles": "CC(=O)Oc1ccccc1C(=O)O", "quantity": 1}],
        shipping_address_id="addr_123",
    )
    client.molecules.orders(limit=20)
    client.molecules.status(order_number="MF-20260527-ABC123EF")

    # Jobs
    client.jobs.history(limit=20)
    client.jobs.status("job_123")
    client.jobs.wait("job_123", poll_interval=5, timeout=1800)

Reliability patterns

Explicit idempotency and timeout handlingPython
from omtx import JobTimeoutError, OMTXError, OmClient

with OmClient() as client:
    try:
        job = client.diligence.deep_diligence(
            query="KRAS mutation treatment pathways",
            preset="quick",
            idempotency_key="dd-kras-2026-02-25",
        )
        result = client.jobs.wait(job["job_id"], timeout=900)
        print(result["status"])
    except JobTimeoutError:
        print("Job did not finish before timeout; resume later with jobs.status(job_id).")
    except OMTXError as exc:
        print("SDK/API error:", exc)