API Reference
Quickstart Authentication Rate limits
Endpoints
POST /score POST /details GET /proteins GET /targets GET /me POST /dock POST /generate
Examples
Python cURL R Notebook Methods Pipeline

VectaBind API

The VectaBind REST API lets you score compound libraries against 473 disease targets programmatically. Integrate binding affinity predictions directly into your drug discovery pipeline — or use the interactive app for Hit Triage Workbench (CSV upload, indication panels, multi-target selectivity heatmaps) with no code.

Base URL: https://api.vectabind.com  ·  Model: Stage6 SE(3)-EGNN + ESM2-3B  ·  MAE: 0.20 pKd

Quickstart

Get your first prediction in under a minute. Get a free API key (instant email), then:

BASH
# Score a compound against EGFR
curl -X POST https://api.vectabind.com/score \
     -H "Content-Type: application/json" \
     -H "X-API-Key: vb_your_key_here" \
     -d '{"smiles": ["CC(=O)Nc1ccc(O)cc1"], "protein_id": "egfr"}'
RESPONSE
{
  "protein_id": "egfr",
  "results": [
    {
      "rank": 1,
      "smiles": "CC(=O)Nc1ccc(O)cc1",
      "affinity": 6.84,
      "bind_prob": 0.73,
      "mw": 151.2,
      "logp": 1.35,
      "qed": 0.72,
      "lipinski_ok": true,
      "drug_like": true
    }
  ],
  "n_valid": 1,
  "n_total": 1
}

affinity is the predicted pKd value (higher = tighter binding). bind_prob is the probability the compound is an active binder (0–1). Batch responses also include mw, logp, qed, lipinski_ok, and drug_like for med-chem triage.

Authentication

All requests require an API key passed in the X-API-Key header:

BASH
-H "X-API-Key: vb_your_key_here"

# Or as a Bearer token
-H "Authorization: Bearer vb_your_key_here"

API keys are prefixed with vb_. Keep your key secret — it controls your monthly quota. Email us to rotate a compromised key.

Rate limits

TierMonthly limitTargetsDockingBatch size
Free500 scores70+ targets10
Pro50,000 scoresAll 4731,000
EnterpriseUnlimitedAll 473 + custom10,000

When you exceed your limit you'll receive a 429 response with your current usage and limit. Usage resets on the 1st of each month.

POST /score

Score one or more compounds against a protein target. Returns predicted pKd and binding probability for each valid SMILES.

POST /score Core scoring endpoint
ParameterTypeRequiredDescription
smilesstring[]requiredArray of SMILES strings to score
protein_idstringoptionalTarget protein ID (default: 10gs). Use GET /proteins for full list.
PYTHON
import requests

response = requests.post(
    "https://api.vectabind.com/score",
    headers={"X-API-Key": "vb_your_key"},
    json={
        "smiles": [
            "CCCOc1cc(N2CCC(Oc3ccc(C(C)NC(=O)c4cnn(C)c4)cc3)C2)ccn1",
            "COC1=CC=C(CC2=CN=C(NC3=NC=C(F)C=C3)S2)C=C1",
        ],
        "protein_id": "egfr"
    }
)

for result in response.json()["results"]:
    print(f"pKd: {result['affinity']:.2f}  Bind: {result['bind_prob']:.0%}  {result['smiles'][:40]}")

POST /details

Get full drug-like properties, VectaBind scoring, and ChEMBL similarity for a single compound.

POST /details Full compound analysis
ParameterTypeRequiredDescription
smilesstringrequiredSingle SMILES string
protein_idstringoptionalTarget protein ID
chembl_lookupbooleanoptionalInclude ChEMBL similarity search (default: true)

GET /proteins

Returns the full list of available protein targets with their IDs.

GET /proteins List all 473+ targets
BASH
curl https://api.vectabind.com/proteins \
  -H "X-API-Key: vb_your_key"

# Response
{"proteins": ["10gs", "11gs", "egfr", ...], "count": 19509}

GET /targets

Returns scoreable targets with gene symbols, PDB IDs, and disease-indication groupings. pdb_id is the production scoring pocket (e.g. EGFR → 2ITK). Powers the app's indication filter and multi-target selectivity panel.

GET /targets Target catalog with disease groups
BASH
curl https://api.vectabind.com/targets \
  -H "X-API-Key: vb_your_key"

# Response (abbreviated)
{
  "targets": [
    {"name": "egfr", "gene": "EGFR", "pdb_id": "2itk", "disease": "oncology_lung"}
  ],
  "disease_groups": [
    {"id": "hematology", "label": "AML / Leukemia / Lymphoma", "targets": ["flt3", "jak2", "btk", ...]}
  ]
}

GET /me

Returns your API tier, monthly usage, and batch size limit. The app displays this as the usage meter (42 / 500 scores · batch 10). The Hit Triage Workbench uses this batch size to chunk library runs — up to 1,000 compounds per score in the browser.

GET /me Usage and tier info
BASH
curl https://api.vectabind.com/me \
  -H "X-API-Key: vb_your_key"

# Response
{"tier": "free", "usage_this_month": 42, "monthly_limit": 500, "batch_size": 10}

POST /dock

Run GNINA docking to get a 3D binding pose and CNN-scored affinity. Pro/Enterprise only.

POST /dock 3D docking — Pro/Enterprise
ParameterTypeRequiredDescription
smilesstringrequiredSMILES of compound to dock
protein_idstringrequiredTarget protein ID

POST /generate

Launch a REINVENT4 generative chemistry job to design novel molecules optimized for a target. Returns a job ID for polling.

POST /generate AI molecule generation
ParameterTypeRequiredDescription
protein_idstringrequiredTarget to optimize for
n_stepsintegeroptionalRL steps (default: 100, max: 500)

Python examples

Screen a compound library

PYTHON
import requests
import pandas as pd

API_KEY = "vb_your_key"
BASE_URL = "https://api.vectabind.com"

# Load your compound library
df = pd.read_csv("compounds.csv")
smiles_list = df["smiles"].tolist()

# Score in batches of 100
results = []
for i in range(0, len(smiles_list), 100):
    batch = smiles_list[i:i+100]
    r = requests.post(
        f"{BASE_URL}/score",
        headers={"X-API-Key": API_KEY},
        json={"smiles": batch, "protein_id": "egfr"}
    )
    results.extend(r.json()["results"])
    print(f"Scored {i+len(batch)}/{len(smiles_list)}")

# Sort by affinity and save top hits
results_df = pd.DataFrame(results)
top_hits = results_df.sort_values("affinity", ascending=False).head(50)
top_hits.to_csv("top_hits.csv", index=False)
print(f"Top hit: pKd {top_hits.iloc[0]['affinity']:.2f}")

Multi-target panel screen (from indication catalog)

PYTHON
import requests
import pandas as pd

API_KEY = "vb_your_key"
BASE = "https://api.vectabind.com"
H = {"X-API-Key": API_KEY}

# Load panel from disease group (matches app indication filter)
catalog = requests.get(f"{BASE}/targets", headers=H).json()
hem = next(g for g in catalog["disease_groups"] if g["id"] == "hematology")
targets = hem["targets"]

df = pd.read_csv("library.csv")
smiles = df["smiles"].tolist()

rows = []
for target in targets:
    for i in range(0, len(smiles), 10):
        batch = smiles[i:i+10]
        r = requests.post(f"{BASE}/score", headers=H,
            json={"smiles": batch, "protein_id": target})
        for hit in r.json()["results"]:
            rows.append({"target": target, **hit})

panel = pd.DataFrame(rows)
panel.to_csv("selectivity_panel.csv", index=False)

Single-compound multi-target screen

PYTHON
import requests

API_KEY = "vb_your_key"
TARGETS = ["egfr", "bace1", "jak2", "kras"]
SMILES = "CCCOc1cc(N2CCC(Oc3ccc(C(C)NC(=O)c4cnn(C)c4)cc3)C2)ccn1"

for target in TARGETS:
    r = requests.post(
        "https://api.vectabind.com/score",
        headers={"X-API-Key": API_KEY},
        json={"smiles": [SMILES], "protein_id": target}
    )
    result = r.json()["results"][0]
    print(f"{target.upper():8s}  pKd: {result['affinity']:.2f}  Bind: {result['bind_prob']:.0%}")

cURL examples

BASH
# Score a single compound
curl -X POST https://api.vectabind.com/score \
  -H "Content-Type: application/json" \
  -H "X-API-Key: vb_your_key" \
  -d '{"smiles":["CCO"],"protein_id":"egfr"}'

# Get all available proteins
curl https://api.vectabind.com/proteins \
  -H "X-API-Key: vb_your_key"

# Full compound details + ChEMBL lookup
curl -X POST https://api.vectabind.com/details \
  -H "Content-Type: application/json" \
  -H "X-API-Key: vb_your_key" \
  -d '{"smiles":"CCO","protein_id":"egfr","chembl_lookup":true}'

R examples

R
library(httr)
library(jsonlite)

api_key <- "vb_your_key"

response <- POST(
  "https://api.vectabind.com/score",
  add_headers("X-API-Key" = api_key),
  content_type_json(),
  body = toJSON(list(
    smiles = c("CC(=O)Nc1ccc(O)cc1", "CCO"),
    protein_id = "egfr"
  ), auto_unbox = TRUE)
)

results <- fromJSON(content(response, "text"))$results
print(results[, c("smiles", "affinity", "bind_prob", "confidence")])

R — indication panel from catalog

R
catalog <- fromJSON(content(GET(
  "https://api.vectabind.com/targets",
  add_headers("X-API-Key" = api_key)
), "text"))

targets <- catalog$disease_groups[[which(sapply(catalog$disease_groups, function(g) g$id) == "hematology")]]$targets
smiles <- read.csv("library.csv")$smiles

for (target in targets) {
  r <- POST("https://api.vectabind.com/score",
    add_headers("X-API-Key" = api_key),
    content_type_json(),
    body = toJSON(list(smiles = smiles, protein_id = target), auto_unbox = TRUE))
  print(target, nrow(fromJSON(content(r, "text"))$results))
}

Jupyter notebook snippet

PYTHON
# pip install requests pandas matplotlib
import requests, pandas as pd, matplotlib.pyplot as plt

API_KEY = "vb_your_key"
df = pd.read_csv("library.csv")
r = requests.post("https://api.vectabind.com/score",
    headers={"X-API-Key": API_KEY},
    json={"smiles": df.smiles.tolist(), "protein_id": "egfr"})
res = pd.DataFrame(r.json()["results"])
res = res.merge(df, on="smiles", how="left")

plt.scatter(res.logp, res.affinity, c=res.confidence.map({"high":"C0","medium":"C1","low":"C2"}))
plt.xlabel("LogP"); plt.ylabel("pKd"); plt.title("SAR view — EGFR"); plt.show()

Pipeline integration

VectaBind works best as a fast filter early in your pipeline — before expensive docking or synthesis:

PYTHON
import requests

def vectabind_filter(smiles_list, target, min_pkd=6.0, min_bind=0.6, api_key=""):
    """Filter compounds by predicted binding affinity."""
    r = requests.post(
        "https://api.vectabind.com/score",
        headers={"X-API-Key": api_key},
        json={"smiles": smiles_list, "protein_id": target}
    )
    results = r.json()["results"]
    
    # Keep only predicted binders above threshold
    hits = [
        res for res in results
        if res["affinity"] >= min_pkd
        and res["bind_prob"] >= min_bind
    ]
    
    print(f"Filtered {len(smiles_list)} → {len(hits)} compounds")
    return [h["smiles"] for h in hits]

# Example: filter 10k compounds to top predicted binders
# before sending to expensive docking
library = load_your_library()           # 10,000 compounds
hits = vectabind_filter(               # → ~200-500 hits
    library, "egfr",
    min_pkd=7.0, min_bind=0.75,
    api_key="vb_your_key"
)
# Now dock only the top hits
run_gnina_docking(hits)

Ready to get started?

Get a free API key and score your first 500 compounds today. No credit card required.

Get free API key →