Skip to content

Embeddings

POST /v1/embeddings turns protein sequences into protein language-model embeddings, from ESMC (Biohub) or SaProt (Westlake University): numeric vectors you can feed to a classifier, a clustering run, similarity search or any downstream model. It returns a job to poll (see Jobs). No structure prediction, no MSA. Every example sends your key from $JAPANFOLD_API_KEY (see Authentication).

Two kinds of vector

For every sequence you get both:

  • Per-residue, shape [length, d_model]. For residue-level tasks (contact or site prediction, per-position features). The <cls>/<eos> boundary tokens are stripped, so row i is residue i.
  • Pooled, shape [d_model], the per-residue vectors combined (see pool). For one vector per protein: similarity, clustering, a sequence-level classifier.

d_model depends on the model and comes back in the results: 960 for esmc-300m, 1152 for esmc-600m, 2560 for esmc-6b, 1280 for both SaProt sizes. saprot-1.3b is deeper than saprot-650m, not wider, so the vector width is the same.

Input

Provide exactly one of these, as on Predictions.

1. sequence: a single chain

curl -s -X POST https://api.japanfold.aiand.com/v1/embeddings \
  -H "Authorization: Bearer $JAPANFOLD_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"model":"esmc-600m","sequence":"MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQ"}'

2. sequences: a list, to embed many in one job

Each item is a bare string or an object {"sequence": "...", "id": "..."}:

curl -s -X POST https://api.japanfold.aiand.com/v1/embeddings \
  -H "Authorization: Bearer $JAPANFOLD_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "model":"esmc-600m",
    "sequences":[
      {"id":"a","sequence":"MKTAYIAKQRQISFVKSHFSRQLEE"},
      {"id":"b","sequence":"GIVEQCCTSICSLYQLENYCN"}
    ]
  }'

3. input: one FASTA string

curl -s -X POST https://api.japanfold.aiand.com/v1/embeddings \
  -H "Authorization: Bearer $JAPANFOLD_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"model":"esmc-600m","input":">a\nMKTAYIAKQRQISFVKSHFSRQLEE\n>b\nGIVEQCCTSICSLYQLENYCN"}'

Models

Set model, default esmc-600m: esmc-300m, esmc-600m, esmc-6b, saprot-650m, saprot-1.3b. Larger is a stronger representation at more compute per sequence. SaProt is trained on sequence + structure tokens and runs sequence-only here (structure tokens masked), which the 1.3B variant is explicitly trained for. See Models & limits.

Parameters

Pass a params object.

Key Type Default Notes
pool enum mean How per-residue vectors become the pooled vector: mean, max, or cls (the <cls> token).
format enum npz npz: per-residue + pooled, one file per sequence. parquet: pooled vectors only, one table.
fast bool false Higher throughput, may be slightly less precise.
curl -s -X POST https://api.japanfold.aiand.com/v1/embeddings \
  -H "Authorization: Bearer $JAPANFOLD_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"model":"esmc-600m","sequence":"MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQ","params":{"pool":"mean","format":"npz"}}'

Results

Once results_ready is true, GET /v1/jobs/{id}/results carries kind: "embed", the model, pool, format, d_model, a sequences list ({id, length, file} per input) and an artifacts list of download URLs.

  • npz (default): one <id>.npz per sequence with arrays per_residue [length, d_model], pooled [d_model] and sequence.
  • parquet: a single embeddings.parquet holding the pooled matrix, one row per sequence. Per-residue vectors are ragged, so they are not in the table; use npz for those.

Download individual files from their artifact url, or the whole set from GET /v1/jobs/{id}/archive.

End to end (Python)

import io, os, time, httpx, numpy as np

AUTH = {"Authorization": f"Bearer {os.environ['JAPANFOLD_API_KEY']}"}
with httpx.Client(base_url="https://api.japanfold.aiand.com", headers=AUTH, timeout=60, follow_redirects=True) as c:
    job = c.post("/v1/embeddings", json={"model": "esmc-600m",
                                         "sequence": "MKTAYIAKQRQISFVKSHFSRQLEERLGLIEVQ"}).json()
    while job["status"] not in ("succeeded", "failed", "canceled"):
        time.sleep(3)
        job = c.get(f"/v1/jobs/{job['id']}").json()
    res = c.get(f"/v1/jobs/{job['id']}/results").json()
    data = np.load(io.BytesIO(c.get(res["artifacts"][0]["url"]).content))
print(data["per_residue"].shape, data["pooled"].shape)  # (L, d_model) (d_model,)

With the JapanFold skill installed, ask instead: "Embed these sequences with ESMC-600M and save the pooled vectors."

Embed jobs wait the same way (?wait=60 on the poll, or Prefer: wait[=seconds]) and accept the same Idempotency-Key header as predictions (see Predictions).

Limits

At most 50 sequences per submission and 2000 residues per sequence (1968 for esmc-6b), higher than the folding cap because embeddings run the language model only. Over a cap you get 400, over a rate limit 429. See Models & limits and Errors.