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 4,541 proteins (19,134 pocket structures) 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.

Your structures are not retained. SMILES sent to /score are held in memory, scored, returned, and dropped — never written to disk. Usage accounting records a hashed key, a month, and a count, with no structures attached. Full details.

Base URL: https://api.vectabind.com  ·  Model: Stage6 — ligand graph + ESM2-3B pocket sequence (the equivariant pathway is inactive)  ·  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 limitTargetsBatch size
Free2,000 scores · 150 docking runsall scoreable targets100
Pro50,000 scoresAll 4,5411,000
EnterpriseUnlimitedAll 4,541 + 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 4,541 protein 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 / 2,000 scores · batch 100). 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

Live. Docking runs AutoDock Vina 1.2.7 against the deposited structure for the target, with waters and crystallisation additives removed. Redocking 507 known ligands into their own receptors reproduces the crystal pose to a median 0.99 Å RMSD (76% within 2.0 Å). Free tier includes 150 runs a month, Pro 10,000.

Returns a docked 3D pose and the Vina binding energy in kcal/mol. The pose is for visualisation and inspection; it is not used for ranking — that comes from the affinity model, which ties with Vina at roughly 1/125th the compute.

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 →