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: starting → synthesis → rescoring → complete. 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6021469c31250dbfa7c8f4161eedc8252d3474ad5471f2b2b85cff16d3b1409
|
|
| MD5 |
5ba8477f4a68f3140d0d19e8a0ec04d7
|
|
| BLAKE2b-256 |
e8abd6b99a25c2b910fe076053bcf3bcdab786ad7ee7f87fe729eb81526c30d8
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ef06e24275234419b6ba5de54bbefa05641212a64b579cd366b39f18ba94768
|
|
| MD5 |
3f9a742b0cf2890407b3eabb0f8075e1
|
|
| BLAKE2b-256 |
68be12ab395eea986407cafcb435adb2060d4dc12a002fa57e4be80ad7f123e9
|