Skip to main content

Python client for the onepot API

Project description

onepot-python

Python client for the onepot API — find purchasable analogs of your query molecules, with optional retrosynthesis decomposition and per-position building-block filtering.

Installation

uv add onepot
# or
pip install onepot

Quick start

from onepot import Client

client = Client(api_key="your-api-key")

resp = client.search(
    smiles_list=["c1ccc(NC(=O)c2ccccc2)cc1"],
    max_results=10,
)
for r in resp["queries"][0]["results"]:
    print(r["smiles"], r["similarity"], r["price_usd"])

Features

  • Similarity search — Tanimoto nearest analogs from the onepot catalog
  • Substructure search — purchasable molecules containing a SMILES/SMARTS pattern
  • Decomposition + BB filters — inspect the retro paths the system considered for your query, then refine which candidate BBs are eligible per position
  • Risk and price filters — exclude results above a chemistry-risk, supplier-risk, or price threshold
  • Streaming — single-molecule searches with SSE progress updates
  • Ordering — submit results for synthesis quoting

Search

Basic

resp = client.search(smiles_list=["c1ccc(-c2ccccc2)cc1"], max_results=10)
curl -X POST https://api.onepot.ai/v1/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{"smiles_list": ["c1ccc(-c2ccccc2)cc1"], "max_results": 10}'

Streaming

For single-molecule searches with real-time progress events. Status lifecycle: startingsynthesisrescoringcomplete. The final event includes a results list with the same fields as the batch endpoint.

for event in client.search_stream("c1ccc(NC(=O)c2ccccc2)cc1", max_results=10):
    print(event["status"], event["message"])
    if event["status"] == "complete":
        results = event["results"]
curl -sN -X POST https://api.onepot.ai/v1/search/stream \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{"smiles": "c1ccc(NC(=O)c2ccccc2)cc1", "max_results": 5}'

Substructure search

Pass substructure_search=True to return purchasable molecules that contain the query as a substructure, instead of similarity hits. The query can be a SMILES or a SMARTS pattern.

resp = client.search(
    smiles_list=["c1ccc(C(=O)N)cc1"],
    max_results=10,
    substructure_search=True,
)
curl -X POST https://api.onepot.ai/v1/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{"smiles_list": ["c1ccc(C(=O)N)cc1"], "max_results": 10, "substructure_search": true}'

Risk and price filters

All optional. When set, results that exceed the threshold are excluded.

Parameter Type Values
max_price int USD, e.g. 200, 500
max_supplier_risk string "low", "medium", "high"
max_chemistry_risk string "low", "medium", "high"

Setting max_chemistry_risk automatically includes the chemistry_risk field in the response. Pass include_chemistry_risk_score=True for the raw probability score.

resp = client.search(
    smiles_list=["c1ccc(-c2ccccc2)cc1"],
    max_results=10,
    max_price=500,
    max_supplier_risk="medium",
    max_chemistry_risk="low",
    include_chemistry_risk_score=True,
)

Decompose & bb_filters

Use decompose=True to receive the retrosynthetic paths the system considered for each query — every reaction_class it found and the BB SMILES of your query at each position. Then call back with bb_filters to constrain which candidate BBs are eligible per position. Every enumerated result is automatically tagged with the reaction_class it was made from and the bbs that built it.

Call 1 — discover.

resp = client.search(
    smiles_list=["c1ccc(NC(=O)c2ccccc2)cc1"],
    max_results=5,
    decompose=True,
)
decompositions = resp["queries"][0]["decompositions"]
rxn = decompositions[0]["reaction_class"]   # e.g. "rxn_5e820be4"

Call 2 — refine. Force the building block at position 1 to vary (Tanimoto ≤ 0.7 to the query's position-1 BB) while leaving position 0 free.

resp = client.search(
    smiles_list=["c1ccc(NC(=O)c2ccccc2)cc1"],
    max_results=10,
    bb_filters=[{"reaction_class": rxn, "bb_index": 1, "max_similarity": 0.7}],
)
for r in resp["queries"][0]["results"]:
    if r.get("reaction_class") == rxn:
        bb_smiles = [b["smiles"] for b in r["bbs"]]
        print(r["smiles"], "←", " + ".join(bb_smiles))
curl -X POST https://api.onepot.ai/v1/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{
    "smiles_list": ["c1ccc(NC(=O)c2ccccc2)cc1"],
    "max_results": 10,
    "bb_filters": [
      {"reaction_class": "rxn_<from-call-1>", "bb_index": 1, "max_similarity": 0.7}
    ]
  }'

reaction_class values like "rxn_5e820be4" come from a prior decompose=True response and are stable across calls — pass them through as strings. Each bb_filters entry takes optional min_similarity and max_similarity (Tanimoto, 0.0–1.0); omit a bound to leave that side open. Combine multiple entries to constrain multiple positions in one call. bb_index is the 0-based position of the building block within the reaction, matching the ordering in the bbs field of a decomposition or annotated result. Unknown reaction_class or min_similarity > max_similarity is rejected as 422. Streaming searches accept the same parameters via client.search_stream(...).

When a retro decomposition produces multiple paths under the same reaction_class, filters apply to each path's candidates independently (similarity is measured against that path's BB SMILES, so the same SMILES can pass one path's filter and fail another's).

Response shape

{
    "queries": [
        {
            "query_smiles": "c1ccc(NC(=O)c2ccccc2)cc1",
            "query_inchikey": "...",
            "results": [
                {
                    "smiles": "...",
                    "inchikey": "...",
                    "similarity": 0.92,
                    "price_usd": 590,
                    "supplier_risk": "low",
                    "chemistry_risk": "medium",       # if include_chemistry_risk=True
                    "chemistry_risk_score": 0.5,      # if include_chemistry_risk_score=True
                    # present on enumerated results (synthesized analogs):
                    "reaction_class": "rxn_5e820be4",
                    "bbs": [
                        {"bb_index": 0, "smiles": "<bb-smiles>"},
                        {"bb_index": 1, "smiles": "<bb-smiles>"},
                    ],
                },
                ...
            ],
            # if decompose=True:
            "decompositions": [
                {
                    "reaction_class": "rxn_5e820be4",
                    "bbs": [
                        {"bb_index": 0, "smiles": "<bb-smiles>"},
                        {"bb_index": 1, "smiles": "<bb-smiles>"},
                    ],
                },
                ...
            ],
        },
        ...
    ],
    "credits_used": 10,
    "credits_remaining": 990,
}

Order

Submit results for synthesis quoting. Returns an order_id you can reference in followup.

order = client.order(
    smiles=["CCO", "c1ccccc1"],
    email="you@example.com",
    notes="Optional notes",
)
# {"order_id": "a1b2c3d4-...", "molecule_count": 2}
curl -X POST https://api.onepot.ai/v1/order \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{
    "smiles": ["CCO", "c1ccccc1"],
    "email": "you@example.com",
    "notes": "Optional notes"
  }'

Pricing

Credits are charged per SMILES in the query. Only the chemistry-risk tier affects pricing:

Option Credits per SMILES
Base search 1
include_chemistry_risk=True 5
include_chemistry_risk_score=True 10

decompose, bb_filters, and substructure_search don't change the price.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

onepot-0.2.0.tar.gz (5.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

onepot-0.2.0-py3-none-any.whl (6.4 kB view details)

Uploaded Python 3

File details

Details for the file onepot-0.2.0.tar.gz.

File metadata

  • Download URL: onepot-0.2.0.tar.gz
  • Upload date:
  • Size: 5.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for onepot-0.2.0.tar.gz
Algorithm Hash digest
SHA256 e6021469c31250dbfa7c8f4161eedc8252d3474ad5471f2b2b85cff16d3b1409
MD5 5ba8477f4a68f3140d0d19e8a0ec04d7
BLAKE2b-256 e8abd6b99a25c2b910fe076053bcf3bcdab786ad7ee7f87fe729eb81526c30d8

See more details on using hashes here.

File details

Details for the file onepot-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: onepot-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 6.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for onepot-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6ef06e24275234419b6ba5de54bbefa05641212a64b579cd366b39f18ba94768
MD5 3f9a742b0cf2890407b3eabb0f8075e1
BLAKE2b-256 68be12ab395eea986407cafcb435adb2060d4dc12a002fa57e4be80ad7f123e9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page