REST API

The server describes itself at /openapi.json, with interactive documentation at /docs. This page is the map.

Documents

Route

Does

GET /api/session

The open documents, the one to show first, and what the server can do.

GET /api/documents

List open documents with revision, filename and dirty state.

POST /api/documents

A new document: empty, from a document’s JSON (document), or imported (format, data). A finished QVF job container opens with its drawing, the result geometry as a new conformer and, under result, the job, its status, the energy and the program that ran it.

GET /api/documents/{id}

The document, its revision (also as ETag), warnings, its file, and the result of the job container it was opened from (else null).

PUT /api/documents/{id}

Replace it. Needs If-Match with the revision it is based on.

PUT /api/documents/{id}/canvas

Replace the drawing (KET); species and reactions are derived from it.

POST /api/documents/{id}/import

Draw structures from format/data, appended or replacing.

POST /api/documents/{id}/clean

Standard bond lengths and angles for every molecule; a molecule it cannot clean without changing its stereochemistry is left and named in warnings.

POST /api/documents/{id}/tidy

Lays the reaction scheme out as papers draw it (Tidy scheme); width (bond lengths, default 24, at least 4) bounds a row. Divergent and convergent schemes branch off the row. A scheme that would read as different reactions, or that branches in a way the layout cannot express, is refused with 422 and the reason; nothing changes.

POST /api/documents/{id}/embed

3D structures for species (all by default), count conformers each; replace re-embeds. Species that fail are named in warnings; when nothing changes, the revision stays.

POST /api/documents/{id}/relax

Relaxes the 3D structures of species (all by default) with FIRE on force_field (mmff94, uff), holding constraints exactly (one species then), to fmax kcal/mol/Å within max_steps; answers with relaxed per species (energies, steps, convergence, constraint checks). Species that fail are named in warnings; when nothing changes, the revision stays.

POST /api/documents/{id}/inputs

One writer’s input for several species with one spec, as JSON or a zip (format); refused species are listed with the reasons.

POST /api/documents/{id}/reactions/{rid}/mapping

A reaction’s atom mapping for review: pairs, bond changes, ambiguous with alternatives, and refusals; pins (m1:3=m3:5) correct it.

POST /api/documents/{id}/reactions/{rid}/neb

Nudged-elastic-band inputs (program orca or vibeqc, spec with kind, method, basis, images …) and the mapping, as JSON or a zip; 422 with reasons and the mapping when refused.

POST /api/documents/{id}/submit

Inputs for species, for the species of reactions (reactants, reagents and products, each once; [] means every reaction), or for all species when neither is given, with program (orca, vibeqc) and spec, submitted to vibe-scheduler as one group; embeds what has no 3D structure, records the jobs and runs (with the queue’s directory, a container’s file and the run’s group), answers with group, submitted (each with its input: container, script or directory), refused and fallbacks. 404 for a reaction the document lacks. A vibe-qc job goes as a QVF job container unless container is false; when none can be built or pinned, the run script goes and fallbacks says why. 503 without vibe-queue.

GET /api/documents/{id}/runs

The document’s runs with their state in vibe-scheduler, and where each result is (directory, container).

POST /api/documents/{id}/results

Import a verified result onto a recorded run; revision, source basename and base64 output bytes, never a server path. See results.

POST /api/documents/{id}/results/spectrum

A run’s IR, Raman or UV-Vis line list as CSV or text, or its broadened spectrum as text; see results.

GET /api/documents/{id}/results/nmr?run=&reference=

A run’s NMR shieldings and shifts against a reference run, as JSON or a CSV, Markdown or LaTeX line list; nucleus filters by element.

POST /api/documents/{id}/results/nmr-labels

Place a run’s shifts as text beside its species’ drawn atoms; revision, run, reference and optional nuclei.

POST /api/documents/{id}/results/report

Compute an explicit group/run comparison as JSON, derived SVG, QVF, CSV, Markdown or LaTeX, with optional reaction coefficients.

GET /api/documents/{id}/groups

The document’s run groups, newest first: each group’s runs, species, program, task, method, a tally of its runs’ states and whether it has finished.

POST /api/documents/{id}/groups/{group}/cancel

Cancel the group’s runs that have not finished; answers with the runs cancelled. 404 when no run belongs to the group.

GET /api/documents/{id}/recipes

The staged recipes (?recipe=ID for one): each with every stage resolved per species to vibe-qc’s run_job keywords, what the operator supplies at launch, and the refusals.

PUT /api/documents/{id}/recipes/{recipe}

Save recipe (its id must be the path’s), replacing one with the same id; answers with the document and the recipe’s report. 422 for a recipe the model refuses.

POST /api/documents/{id}/recipes/{recipe}/campaigns/{campaign}/energies

Explicit stage, optional reactions/coefficients, format (JSON, CSV, Markdown, LaTeX, SVG, QVF); requires fully accepted campaign artifacts.

POST /api/documents/{id}/recipes/baseline

Save the publication baseline (MACE, PBE/def2-SVP, same-surface Hessian, DLPNO-CCSD(T)) as id for species or the species of reactions ([] for the scheme).

POST /api/documents/{id}/recipes/{recipe}/remove

Remove a recipe; 404 when there is none.

POST /api/documents/{id}/recipes/{recipe}/campaigns

Compile the recipe into a vibe-scheduler campaign in directory (absolute, new or empty), with optional id, host, program, python, runner, cpus, mem_mb and accept_model_license; answers with the document, the campaign record and the run_command. 422 with every reason when it cannot.

GET /api/documents/{id}/recipes/{recipe}/campaigns/{campaign}

The campaign’s stages: process state and attempts in vibe-scheduler’s journal, and scientific acceptance with the validator’s verdict. 503 without vibe-queue.

POST /api/documents/{id}/recipes/{recipe}/campaigns/{campaign}/renders

Same-orientation renders of species into directory (absolute, new or empty), width and height in pixels, publication, images; answers with the record (as renders.json), the files and the warnings. 422 when an artifact is not the one vibe-scheduler verified.

POST /api/documents/{id}/recipes/{recipe}/campaigns/{campaign}/retry

Authorise the next attempt of the failed node; 409 when the node has not failed.

POST /api/documents/{id}/view

Shows species in vibe-viewer as a QVF; 422 without a 3D structure, 503 when the viewer is missing or fails to start. A standalone launch selects a free loopback port and waits up to 45 seconds for readiness. GET /api/session says which route applies ("viewer").

PATCH /api/documents/{id}/species/{species}

Set a compound number, multiplicity or name.

GET /api/documents/{id}/report

Formula, masses, elemental analysis, calculated descriptors, identifiers and checked name per species.

POST /api/documents/{id}/highlights

Mark atoms of a species, numbered from 1, in a palette colour; revision, species, atoms, colour.

POST /api/documents/{id}/highlights/selection

Mark the atoms drawn at points in the canvas’s own ket; revision and colour.

POST /api/documents/{id}/highlights/clear

Remove every highlight, or those of species; revision.

POST /api/documents/{id}/highlights/points

Where the marked atoms are drawn in a posted ket, by colour, for a client to show them.

GET /api/documents/{id}/abbreviations

The labels that can be contracted (available) and those contracted in each species (species).

POST /api/documents/{id}/abbreviations

Draw groups such as Ph, Boc or OTf as their label; revision, optional species and labels (default: every known group). The structure is unchanged; 422 when none is found.

POST /api/documents/{id}/abbreviations/expand

Draw contracted groups as their atoms again; revision, optional species and labels.

POST /api/documents/{id}/nanostructures

Generate a nanostructure and add it as a species; revision, parameters (see nanostructures), optional species_id, label, charge, multiplicity; the response adds a nanostructure summary, 422 with the reason when refused.

POST /api/documents/{id}/species/{species}/picture

Put a picture of a nanostructure species on the canvas; revision, style, label, rear, break, width.

GET /api/documents/{id}/pictures

The nanostructure pictures on the canvas: species, style, box and anchors.

POST /api/documents/{id}/generics/{generic}/attach

Move a labelled structure onto a picture’s anchor; revision, species, anchor.

POST /api/documents/{id}/half-reactions

Draw an electrode half-reaction; revision, reactants, products, electrons, conditions, arrow.

GET /api/documents/{id}/balance

Each reaction’s atoms and charge per side with its electrons, the imbalance and whether it balances.

POST /api/documents/{id}/tlc

Draw a TLC plate beside the drawing; revision and lanes, each a label and the spots’ Rf values.

POST /api/documents/{id}/generics/{generic}/cap

Make a species of a labelled structure by capping its labels; revision and cap (H or CH3); 422 with the reason when refused.

GET /api/documents/{id}/generics

The R-group cores, bracketed groups and labelled structures (generics; a labelled one lists its labels and capped species) and R-group definitions (rgroups) derived from the drawing.

GET /api/documents/{id}/stereo

Each species’ CIP descriptors, undefined stereo and enhanced-stereo groups.

POST /api/documents/{id}/stereo-labels

Write the descriptors into the drawing as labels, or remove them with clear; revision.

PUT /api/documents/{id}/reactions/{reaction}/amounts

Replace a reaction’s entered amounts; revision and amounts, an empty list clearing them.

GET /api/documents/{id}/reactions/{reaction}/stoichiometry?format=json

The worked stoichiometry table as JSON, CSV, Markdown or LaTeX.

GET /api/documents/{id}/properties?format=csv

The species property table as CSV, Markdown or LaTeX.

POST /api/documents/{id}/species/{species}/property-text

Place the species’ properties as text under its structure; revision and optional fields.

GET /api/documents/{id}/export/{format}

The document as a file; ?download=true names it. Figures take ?stereo_labels=true and ?sequences=true; helm and fasta write species imported from a sequence.

POST /api/documents/{id}/save

Write it back to the file the server opened it from; 409 when replacing a QVF would discard result data or other unsupported content.

DELETE /api/documents/{id}

Close it.

Document response fields

Field

Meaning

id

The server session’s document handle, used in URLs; not a species ID or filename

revision

The current revision to use for the next edit

document

Native document JSON, including species, jobs and provenance

warnings

Notices from the operation or stored document; inspect them even after HTTP success

file

The backing file’s name, or null; never an arbitrary server filesystem path

dirty

Whether a file-backed document has changed since that backing file was saved

A document with file: null reports dirty: false even though no file has been saved. Do not use this flag as proof of persistence. Export and retain such documents explicitly. Server document IDs last only for that in-memory session; reopening the same VSK in another session creates a new handle. Species IDs inside the document have their own identity rules.

Revisions and concurrent edits

Replacing a whole document requires If-Match, for example If-Match: "2". Canvas replacement, import, cleanup, embedding, species edits and submission instead require a JSON revision field. In particular, PUT .../canvas uses revision, not If-Match. Use the revision returned by the latest read or successful edit; do not assume every request increments it.

A stale edit answers 409, or 412 for whole-document replacement, with the current revision in detail.revision. Read the latest document, reconcile your intended change with it, and then resubmit. Retrying an old whole-document snapshot with a new revision can overwrite another editor’s work. Whole-document replacement without If-Match returns 428; a malformed header returns 400.

Edit request models also take actor (human, agent or system) and client (for example rest or mcp) for provenance. Consult /openapi.json for each route’s fields. Save and close take neither a revision body nor If-Match; exporting and input generation do not edit the stored document.

Whole-document PUT validates and replaces the supplied model. It does not rederive species from the canvas or automatically append a provenance edit; its store advances the revision. Prefer the specific canvas, import or species routes when you want their derivation and edit-recording behavior.

Request body shapes

The state response wrapper is not itself a document. When sending a document back, extract its document field and use the shape required by that route:

Operation

JSON body

Create from an existing document

{"document": DOCUMENT}

Create/import from chemistry text

{"format": "smiles", "data": "CCO"}; a stored-document import also needs revision

Replace the whole document

DOCUMENT directly, with If-Match in the headers

Validate, stateless clean/report/export

DOCUMENT directly

Replace the canvas

{"revision": N, "ket": KET_OBJECT}

Stateless input generation

{"document": DOCUMENT, "species": "ID", "program": "WRITER", "spec": SPEC}

Stored-document input generation

{"program": "WRITER", "spec": SPEC} with optional species list and output format

DOCUMENT, N, KET_OBJECT and SPEC above are placeholders for actual JSON values. Do not send them literally. Save and close have no request body. Use the running server’s OpenAPI schema for required fields and constraints.

A first request

Start vibe-sketcher serve and use the address it prints. For the default port:

curl --fail-with-body http://127.0.0.1:8766/api/documents \
  -H 'Content-Type: application/json' \
  -d '{"format":"smiles","data":"CCO","actor":"agent","client":"rest"}'

The response contains id, revision, document, warnings, file and dirty. Use the returned id in subsequent URLs and the returned revision when embedding or editing. The downloadable REST example performs the full create, embed, write-input and export sequence.

Documents created through REST live in the server’s memory and have no backing file. Export them and save the returned bytes to keep them across server restarts. /save writes only to a file already associated with the document; it returns 409 when there is no backing file. It does not accept a destination path. Closing a document removes it from the session without saving it.

For stored-document input generation, embed first. A successful JSON response can contain both files and refused; HTTP 200 does not mean every species succeeded. A ZIP includes REFUSED.txt for partial refusals, and an all-refused batch returns 422. Submission similarly returns submitted and refused; inspect recorded runs before retrying a partially successful submission.

Updating species metadata

PATCH /api/documents/{id}/species/{species} accepts revision, label, name and multiplicity, plus the edit’s actor and client. Omitted fields and JSON null leave existing values unchanged. To clear a compound label or user name, send an empty string:

{"revision": 2, "label": "", "name": "", "actor": "agent", "client": "rest"}

Replace 2 with the document’s current revision. A nonempty user name is stored with source user and confidence high; this records authorship, not an independent chemical verification. Clearing it allows the properties report to show the naming engine’s result again when available.

Multiplicity must be a positive integer compatible with the species’ electron count when that can be checked. This endpoint does not accept a charge or SMILES change: edit/import the chemical structure to change those. It also does not edit text labels on the canvas. See document identity for how later canvas edits reconcile species metadata.

Validation responses

POST /api/documents/validate takes the document JSON itself, without a document wrapper. For a syntactically valid JSON body, it returns HTTP 200 with valid and errors, even when the document fails validation. Check valid; a successful HTTP request alone does not establish a valid document. Malformed JSON is a request error and returns 422.

curl --fail-with-body http://127.0.0.1:8766/api/documents/validate \
  -H 'Content-Type: application/json' \
  --data-binary @ethanol.vsk

The same validation runs in the Python document model. JSON Schema alone cannot enforce every cross-reference or charge/multiplicity check. See document validation.

Operations without an open document

The chemistry routes below operate on supplied data without creating an open document. Queue inspection and cancellation are also available without one; cancellation changes the external queue run.

Route

Does

POST /api/qvf/overwrite-check

Inspect existing QVF bytes in base64 data; returns allowed and reason. Takes no path and writes nothing. Invalid archives are refused; invalid base64 is 422.

POST /api/convert

format/data to a document.

POST /api/clean

A posted document with its drawing cleaned, and how many molecules were.

POST /api/tidy?width=24

A posted document with its scheme laid out, its rows and how many molecules were cleaned; 422 with the reason when refused.

POST /api/chem/embed3d

3D conformers for one smiles, best first, with force-field energies.

POST /api/chem/relax

One conformer of a smiles relaxed with FIRE on force_field, constraints held; the new conformer, energies, steps and constraint checks.

POST /api/report

The report for a posted document.

POST /api/export/{format}

A posted document as a file.

POST /api/documents/validate

Whether a JSON value is a valid document, with every problem.

GET /api/queue

Whether vibe-scheduler is installed and serving, and which programs it can run.

POST /api/queue/runs/{run}/cancel

Cancel a run; 409 when it has finished.

GET /api/schema/document

The document’s JSON schema.

GET /api/writers, POST /api/inputs

The input writers; see input writers.

Binary data, a QVF archive, goes into data base64-encoded with "encoding": "base64" (on POST /api/documents, /import and /convert). GET /api/session says whether QVF is available ("qvf").

Refusals answer 422 with the reasons, under detail.reasons or detail.errors. Input beyond vibe-sketcher’s bounds is such a refusal; a request body over 272 MiB answers 413. A server on the loopback interface answers 421 to a Host that is not this machine’s and 403 to a request from another site’s Origin; see Security and input bounds. A figure export on a machine without the drawing libraries (see installation) answers 503, with the fix in detail.reasons.

A client writing exported bytes to disk must protect existing QVF results. Inspect the destination through /api/qvf/overwrite-check and confirm that its bytes have not changed before replacement, or use the SDK’s write_output helper. A refusal requires a different Save As destination; exporting an imported result does not preserve its calculation payloads.

Named reactions

See the compound, fragment and named-reaction library for the searchable picker, editable examples, explicit unfinished scaffolds, source coverage and matching SDK, CLI, REST and MCP operations.