SDK Tutorial
Customer walkthrough for using `OmClient` with Generated Data, diligence workflows, ZenCloud, Molecule Fulfillment, jobs, and data loading.
Install and authenticate
Install packagesBash
pip install omtxSet 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())
PYGenerated 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[]plusaccessible_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_scoreSeparate 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 submitted molecules
Score Om Accessible Space, then order selected hitsPython
from pathlib import Path
from uuid import uuid4
import polars as pl
from omtx import OmClient
with OmClient() as client:
job = client.lula2.score(
protein_sequence="YOUR_PROTEIN_SEQUENCE",
source="om",
tier=50,
n=50_000,
top_k=10_000,
idempotency_key="lula2-om-round-1",
)
artifact_paths = []
result_dir = Path("outputs/lula2-om-round-1")
for job_id in job["job_ids"]:
client.jobs.wait(job_id, poll_interval=5, timeout=3600)
artifact_paths.extend(
client.jobs.download_all_artifacts(
job_id,
output_dir=result_dir / job_id,
overwrite=True,
)
)
score_tables = [
pl.read_parquet(path)
for path in artifact_paths
if path.name == "top_hits.parquet"
]
score_rows = pl.concat(score_tables).sort("score", descending=True)
selected_hits = score_rows.head(96).to_dicts()
addresses = client.molecules.shipping_addresses()
order = client.molecules.order(
items=selected_hits,
shipping_address_id=addresses["default_shipping_address_id"],
idempotency_key=f"lula2-om-order-{uuid4()}",
)
print("Selected hits:", len(selected_hits))
print("Order number:", order["order_number"])Search, quote, and order arbitrary submitted SMILESPython
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}],
)
order = client.molecules.order(
items=[{"smiles": "CC(=O)Oc1ccccc1C(=O)O", "quantity": 1}],
shipping_address_id="addr_123",
idempotency_key="molecule-wallet-order-001",
)
print("Provider:", pricing["provider"])
print("Search response keys:", list(hits.keys()))
print("Quote total cents:", quote["total_amount_cents"])
print("Order number:", order["order_number"])Function map for API-key users
Available SDK functions and Wallet order routesPython
import requests
from omtx import OmClient
with OmClient() as client:
# Health and account
client.status()
client.users.profile()
# Wallet funding is explicit only:
# prepared = client.wallet.prepare_topup(amount_cents=12500, idempotency_key="wallet-prepare-demo-001")
# Show prepared["user_approval_confirmation"] and capture fresh approval.
# Only after approval, retain this exact request and key for recovery:
# client.wallet.topup(amount_cents=prepared["amount_cents"], payment_mode="saved_card", funding_operation_id=prepared["funding_operation_id"], user_approval_confirmation=prepared["user_approval_confirmation"], idempotency_key="wallet-fund-demo-001")
# A timeout is unknown: recover the same request; do not prepare another.
# 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}]
response = requests.post(
"https://api.omtx.ai/v2/data-generation/orders",
headers={
"x-api-key": "YOUR_API_KEY",
"Idempotency-Key": "dg-wallet-target-001",
"Content-Type": "application/json",
},
json={"sequences": sequences},
timeout=60,
)
response.raise_for_status()
# 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()
# ZenCloud: inspect the image contract and price, then stage inputs.
print(client.zencloud.describe())
client.artifacts.upload("target.pdb")
# Reserve and run explicitly using client.zencloud.start/run.
# Keep each operation's original key for uncertain-outcome recovery.
# Om Accessible Space score rows can be ordered directly
client.lula2.score(
protein_sequence="YOUR_PROTEIN_SEQUENCE",
source="om",
tier=50,
n=50_000,
top_k=10_000,
)
client.molecules.shipping_addresses()
# Molecule Fulfillment for arbitrary submitted SMILES
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.order(
items=[{"smiles": "CC(=O)Oc1ccccc1C(=O)O", "quantity": 1}],
shipping_address_id="addr_123",
idempotency_key="molecule-wallet-order-001",
)
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)